--- apache_1.3.28.orig/README.v6 Thu Jan 1 01:00:00 1970 +++ apache_1.3.28/README.v6 Fri Jul 25 11:01:55 2003 @@ -0,0 +1,166 @@ +IPv6-ready apache 1.3.x +KAME Project +$Id$ + +This patchkit enables apache 1.3.x to perform HTTP connection over IPv6. +Most of optional modules are left unchanged, i.e. it won't support IPv6, +and it may not compile. + +Basically you can write IPv6 address where IPv4 address fits. + +extra command-line argument: + -4 Assume IPv4 address on ambiguous directives + -6 Assume IPv6 address on ambiguous directives (default) + + 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: + + order deny,allow + deny from all + allow from 10.0.0.0/8 + allow from 3ffe:9999:8888:7777::/64 + + +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 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. + + + If you would like to specify IPv6 numeric address in host part, + use bracketed format like below: + + Note: Now we DO NOT handle old non-bracketed format, + + 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. + + +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. + +Modules known to be incompatible with IPv6 + (please report us) + +configure + Configure has extra option, --enable-rule=INET6. if the option + is specified, IPv6 code will be enabled. + +configuration file + We do not support IPv4 mapped address (IPv6 address format like + ::ffff:10.1.1.1) in configuration file. + +This kit assumes that you have working(*) getaddrinfo() and getnameinfo() +library functions. Even if you don't have one, don't panic. We have +included last-resort version (which support IPv4 only) into the kit. +For more complete implementation you might want to check BIND 8.2. +(*) NOTE: we have noticed that some of IPv6 stack is shipped with broken +getaddrinfo(). In such cases, you should get and install BIND 8.2. + +When compiling this kit onto IPv6, you may need to specify some additional +library paths or cpp defs (like -linet6 or -DINET6). +Now you don't have to specify --enable-rule=INET6. The "configure" script +will give you some warnings if the IPv6 stack is not known to the +"configure" script. Currently, the following IPv6 stacks are supported: +- KAME IPv6 stack, http://www.kame.net/ + use configure.v6 for convenience, +- Linux IPv6 stack, http://www.linux.org/ + use configure.v6 for convenience. +- Solaris 8 IPv6 stack, http://www.sun.com/ + use configure.v6 for convenience. +To disable IPv6 support, specify --disable-rule=INET6 to the "configure" +script. + +CAVEAT: This patchkit may change some of apache module API, to avoid +IPv4-dependent structure member variable. Please let us know if there's +any troubles as we know very little about the apache module API. + +Acknowledgements + Thanks to all people submitted patches/fixes for this patch kit, + including: + "Chris P. Ross" + +Author contacts + Jun-ichiro itojun Hagino, KAME project + http://www.kame.net/ + mailto:core@kame.net +Linux Port + Arkadiusz Miskiewicz, Polish Linux Distribution project (IPv6) + http://www.pld.org.pl/ + mailto:feedback@pld.org.pl + Satoshi SHIDA, Linux IPv6 Users Group JP + http://www.v6.linux.or.jp/ + YOSHIFUJI Hideaki, USAGI Project + http://www.linux-ipv6.org/ --- apache_1.3.28.orig/conf/httpd.conf-dist Wed Jul 16 21:36:41 2003 +++ apache_1.3.28/conf/httpd.conf-dist Fri Jul 25 11:01:55 2003 @@ -174,6 +174,11 @@ #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 --- apache_1.3.28.orig/configure.v6 Thu Jan 1 01:00:00 1970 +++ apache_1.3.28/configure.v6 Fri Jul 25 11:01:55 2003 @@ -0,0 +1,3 @@ +#! /bin/sh + +./configure --enable-rule=INET6 --enable-module=proxy $* --- apache_1.3.28.orig/src/Configuration.tmpl Fri Jul 25 11:00:49 2003 +++ apache_1.3.28/src/Configuration.tmpl Fri Jul 25 11:01:55 2003 @@ -191,6 +191,9 @@ # Rule EXPAT=default : If Expat can be found at the system or # in lib/expat-lite, use it; otherwise # skip it +# INET6: +# IPv6 support. +# # # CYGWIN_WINSOCK: # Use Win32 API system calls for socket communication instead @@ -205,6 +208,7 @@ Rule IRIXN32=yes Rule PARANOID=no Rule EXPAT=default +Rule INET6=no Rule CYGWIN_WINSOCK=no # DEV_RANDOM: --- apache_1.3.28.orig/src/Configure Fri Jul 25 11:00:49 2003 +++ apache_1.3.28/src/Configure Fri Jul 25 11:01:55 2003 @@ -238,6 +238,7 @@ RULE_CYGWIN_WINSOCK=`./helpers/CutRule CYGWIN_WINSOCK $file` RULE_SHARED_CORE=`./helpers/CutRule SHARED_CORE $file` RULE_SHARED_CHAIN=`./helpers/CutRule SHARED_CHAIN $file` +RULE_INET6=`./helpers/CutRule INET6 $file` #################################################################### ## Rule SHARED_CORE implies required DSO support @@ -1724,6 +1725,124 @@ 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="UNKNOWN" + for i in KAME Linux Solaris; do + case "$i" in + KAME) + if [ -f /usr/include/netinet6/in6.h -a "x`egrep '__KAME__' /usr/include/netinet6/in6.h 2>/dev/null`" != "x" ]; then + IPV6_STACKTYPE=$i + fi + ;; + Linux) + if [ /usr/include/netinet/ip6.h -a -d /usr/include/linux ]; then + IPV6_STACKTYPE=$i + fi + ;; + Solaris) + SOL_VERSION=`(uname -v) 2>/dev/null` || SOL_VERSION="unknown" + case "${PLAT}-${SOL_VERSION}" in + *-solaris2.27*-*IPv6*) + if [ -f /etc/hostname -o -f /etc/hostname.[a-z]*[0-9] ]; then + IPV6_STACKTYPE="Solaris 7 (${SOL_VERSION})" + fi + ;; + esac + ;; + esac + if [ "$IPV6_STACKTYPE" != "UNKNOWN" ]; then + break + fi + done + if [ "$IPV6_STACKTYPE" != "UNKNOWN" ]; then + echo " + You seem to be using $IPV6_STACKTYPE stack" + if ./helpers/TestCompile func getaddrinfo; then + echo " - Assuming you have working getaddrinfo in libc" + else + if [ -f /usr/local/v6/lib/libinet6.a -a "x`egrep '^EXTRA_L' Makefile.config | grep linet6`" = "x" ]; then + LIBS="$LIBS -L/usr/local/v6/lib -linet6" + echo " - using getaddrinfo in libinet6" + elif [ -f /usr/local/lib/libinet6.a -a "x`egrep '^EXTRA_L' Makefile.config | grep linet6`" = "x" ]; then + LIBS="$LIBS -L/usr/local/lib -linet6" + echo " - using getaddrinfo in libinet6" + elif [ -f /usr/inet6/lib/libinet6.a -a "x`egrep '^EXTRA_L' Makefile.config | grep linet6`" = "x" ]; then + echo " - using getaddrinfo in libinet6" + else + echo "** WARNING: No getaddrinfo found, linkage may fail" + fi + fi + else + echo "" + echo "** WARNING: We have no explicit knowledge about the IPv6" + echo "** implementation on this host. You may need to specify" + echo "** EXTRA_LIBS so that we can find getaddrinfo() and" + echo "** getnameinfo() library functions." + echo "" + fi + case $PLAT in + *-solaris2* ) + LIBS="$LIBS -lresolv" + ;; + esac +else + CFLAGS="$CFLAGS -DNEED_GETADDRINFO -DNEED_GETNAMEINFO" + if [ -f /usr/include/netdb.h -a "x`egrep 'addrinfo' /usr/include/netdb.h`" = "x" ]; then + CFLAGS="$CFLAGS -DNEED_ADDRINFO" + fi +fi + +echo '#include ' >testfunc.c +echo '#include ' >>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 ' >testfunc.c +echo '#include ' >>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 ' >testfunc.c +echo '#include ' >>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 ' >testfunc.c +echo '#include ' >>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: @@ -2320,6 +2439,38 @@ echo "#define AP_LONGEST_LONG $AP_LONGEST_LONG" >>$AP_CONFIG_AUTO_H echo "#endif" >>$AP_CONFIG_AUTO_H +if [ x`./helpers/TestCompile -r sizeof 'uint32_t'` != x"" ]; then + echo "" >>$AP_CONFIG_AUTO_H + echo "/* determine: use uint32_t as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H + echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H + echo "#define ap_uint32_t uint32_t" >>$AP_CONFIG_AUTO_H + echo "#endif" >>$AP_CONFIG_AUTO_H + echo " - use uint32_t as 32bit unsigned int" +elif [ x`./helpers/TestCompile -r sizeof 'u_int32_t'` != x"" ]; then + echo "" >>$AP_CONFIG_AUTO_H + echo "/* determine: use u_int32_t as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H + echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H + echo "#define ap_uint32_t u_int32_t" >>$AP_CONFIG_AUTO_H + echo "#endif" >>$AP_CONFIG_AUTO_H + echo " - use u_int32_t as 32bit unsigned int" +elif [ x`./helpers/TestCompile -r sizeof 'unsigned int'` = x"4" ]; then + echo "" >>$AP_CONFIG_AUTO_H + echo "/* determine: use unsigned int as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H + echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H + echo "#define ap_uint32_t unsigned int" >>$AP_CONFIG_AUTO_H + echo "#endif" >>$AP_CONFIG_AUTO_H + echo " - use unsigned int as 32bit unsigned int" +elif [ x`./helpers/TestCompile -r sizeof 'unsigned long int'` = x"4" ]; then + echo "" >>$AP_CONFIG_AUTO_H + echo "/* determine: use unsigned long int as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H + echo "#ifndef uint32_t" >>$AP_CONFIG_AUTO_H + echo "#define uint32_t unsigned long int" >>$AP_CONFIG_AUTO_H + echo "#endif" >>$AP_CONFIG_AUTO_H + echo " - use unsigned long int as 32bit unsigned int" +else + echo " - Warning: cannot determine what type should we use as 32bit unsigned int" +fi + #################################################################### ## More building ap_config_auto.h ## --- apache_1.3.28.orig/src/ap/ap_snprintf.c Mon Feb 3 18:13:17 2003 +++ apache_1.3.28/src/ap/ap_snprintf.c Fri Jul 25 11:01:55 2003 @@ -73,6 +73,7 @@ #include #include #include +#include "sa_len.h" #ifdef WIN32 #include #endif @@ -510,6 +511,42 @@ +#ifdef INET6 +static char *conv_sockaddr(struct sockaddr *sa, char *buf_end, int *len) +{ + char *p = buf_end; + char hostnamebuf[MAXHOSTNAMELEN]; + char portnamebuf[MAXHOSTNAMELEN]; + char *q; + int salen; + +#ifndef SIN6_LEN + salen = SA_LEN(sa); +#else + salen = sa->sa_len; +#endif + if (getnameinfo(sa, salen, hostnamebuf, sizeof(hostnamebuf), + portnamebuf, sizeof(portnamebuf), NI_NUMERICHOST | NI_NUMERICSERV)) { + strcpy(hostnamebuf, "???"); + strcpy(portnamebuf, "???"); + } + if (strcmp(portnamebuf,"0") == 0) + strcpy(portnamebuf, "*"); + q = portnamebuf + strlen(portnamebuf); + while (portnamebuf < q) + *--p = *--q; + *--p = ':'; + q = hostnamebuf + strlen(hostnamebuf); + while (hostnamebuf < q) + *--p = *--q; + + *len = buf_end - p; + return (p); +} +#endif /*INET6*/ + + + /* * Convert a floating point number to a string formats 'f', 'e' or 'E'. * The result is placed in buf, and len denotes the length of the string @@ -1057,6 +1094,7 @@ /* print a struct sockaddr_in as a.b.c.d:port */ case 'I': { +#ifndef INET6 struct sockaddr_in *si; si = va_arg(ap, struct sockaddr_in *); @@ -1065,6 +1103,16 @@ if (adjust_precision && precision < s_len) s_len = precision; } +#else + struct sockaddr *sa; + + sa = va_arg(ap, struct sockaddr *); + if (sa != NULL) { + s = conv_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len); + if (adjust_precision && precision < s_len) + s_len = precision; + } +#endif else { s = S_NULL; s_len = S_NULL_LEN; --- apache_1.3.28.orig/src/include/ap.h Mon Feb 3 18:13:17 2003 +++ apache_1.3.28/src/include/ap.h Fri Jul 25 11:01:55 2003 @@ -95,7 +95,8 @@ * 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 + * %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 --- apache_1.3.28.orig/src/include/ap_config.h Mon May 5 13:45:49 2003 +++ apache_1.3.28/src/include/ap_config.h Fri Jul 25 11:01:55 2003 @@ -411,6 +411,10 @@ #endif #ifndef S_IWOTH #define S_IWOTH 000002 +#ifndef rlim_t +typedef int rlim_t; +#endif +typedef u_long n_long; #endif #define STDIN_FILENO 0 @@ -1523,6 +1527,70 @@ #define ap_wait_t int #endif +#ifndef INET6 +#define sockaddr_storage sockaddr +#define ss_family sa_family +#define ss_len sa_len +#else +#include "sockaddr_storage.h" /* sshida@st.rim.or.jp */ +#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 + +#if defined(NEED_GETADDRINFO) || defined(NEED_GETNAMEINFO) +/* + * minimal definitions for fake getaddrinfo()/getnameinfo(). + */ +#ifndef EAI_NODATA +#define EAI_NODATA 1 +#define EAI_MEMORY 2 +#endif + +#ifndef AI_PASSIVE +#define AI_PASSIVE 1 +#define AI_CANONNAME 2 +#define AI_NUMERICHOST 4 +#define NI_NUMERICHOST 8 +#define NI_NAMEREQD 16 +#define NI_NUMERICSERV 32 +#endif +#endif + +#ifdef NEED_GETADDRINFO +#ifdef NEED_ADDRINFO +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +#endif +extern char *gai_strerror(int ecode); +extern void freeaddrinfo(struct addrinfo *ai); +extern int getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res); +#endif +#ifdef NEED_GETNAMEINFO +extern int getnameinfo(const struct sockaddr *sa, size_t salen, + char *host, size_t hostlen, char *serv, size_t servlen, + int flag); +#endif + #ifdef __cplusplus } #endif --- apache_1.3.28.orig/src/include/http_conf_globals.h Fri Jul 25 11:00:49 2003 +++ apache_1.3.28/src/include/http_conf_globals.h Fri Jul 25 11:01:55 2003 @@ -82,7 +82,8 @@ extern API_VAR_EXPORT int ap_max_requests_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; --- apache_1.3.28.orig/src/include/http_vhost.h Mon Feb 3 18:13:19 2003 +++ apache_1.3.28/src/include/http_vhost.h Fri Jul 25 11:01:55 2003 @@ -73,7 +73,7 @@ API_EXPORT(const char *) ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s); /* handle NameVirtualHost directive */ -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); /* 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); --- apache_1.3.28.orig/src/include/httpd.h Fri Jul 25 11:00:49 2003 +++ apache_1.3.28/src/include/httpd.h Fri Jul 25 11:01:55 2003 @@ -904,8 +904,8 @@ /* 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, @@ -947,8 +947,8 @@ 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 */ - unsigned short host_port; /* The bound port, for this server */ + struct sockaddr_storage host_addr; /* The bound address, for this server */ + unsigned short host_port; /* The bound port, for this server XXX */ char *virthost; /* The name given in */ }; @@ -1016,7 +1016,7 @@ /* 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 */ @@ -1184,7 +1184,7 @@ #endif /*#ifdef CHARSET_EBCDIC*/ API_EXPORT(char *) ap_get_local_host(pool *); -API_EXPORT(unsigned long) ap_get_virthost_addr(char *hostname, unsigned short *port); +API_EXPORT(struct sockaddr *) ap_get_virthost_addr(char *hostname, unsigned short *port); extern API_VAR_EXPORT time_t ap_restart_time; --- apache_1.3.28.orig/src/include/sa_len.h Thu Jan 1 01:00:00 1970 +++ apache_1.3.28/src/include/sa_len.h Fri Jul 25 11:01:55 2003 @@ -0,0 +1,41 @@ +/* sa_len.h : tiny version of SA_LEN (written by ) */ + +#include +#include +#include +#include + +#ifndef HAVE_SOCKADDR_LEN +#ifndef SA_LEN +#define SA_LEN(s_) ap_sa_len((s_)->sa_family) + +static NET_SIZE_T ap_sa_len (sa_family_t af) +{ + switch (af){ +#if defined(AF_INET) + case AF_INET: + return (sizeof(struct sockaddr_in)); +#endif /* AF_INET */ +#if defined(AF_INET6) + case AF_INET6: + return (sizeof(struct sockaddr_in6)); +#endif +#ifdef AF_LOCAL + case AF_LOCAL: +#endif /* AF_LOCAL */ +#if defined(AF_UNIX) && (AF_UNIX != AF_LOCAL) + case AF_UNIX: +#endif /* AF_UNIX */ +#if defined(AF_FILE) && (AF_FILE != AF_LOCAL || AF_FILE != AF_UNIX) + case AF_FILE: +#endif /* AF_FILE */ +#if defined(AF_LOCAL) || defined(AF_UNIX) || defined(AF_FILE) + return (sizeof(struct sockaddr_un)); +#endif /* defined(AF_LOCAL) || defined(AF_UNIX) || defined(AF_FILE) */ + default: + return 0; + } + return 0; +} +#endif /* SA_LEN */ +#endif /* HAVE_SOCKADDR_LEN */ --- apache_1.3.28.orig/src/include/sockaddr_storage.h Thu Jan 1 01:00:00 1970 +++ apache_1.3.28/src/include/sockaddr_storage.h Fri Jul 25 11:01:55 2003 @@ -0,0 +1,53 @@ +/* +struct sockaddr_storage + + RFC2553 proposes struct sockaddr_storage. + This is a placeholder for all sockaddr-variant structures. This is + implemented like follows: + + You should use this structure to hold any of sockaddr-variant + structures. +*/ +#ifdef NEED_SOCKADDR_STORAGE + +struct sockaddr_storage { +#ifdef HAVE_SOCKADDR_LEN + u_char ss_len; + u_char ss_family; +#else + u_short ss_family; +#endif + u_char __padding[128 - 2]; +}; + +/* +union sockunion + + Alternatively, you may want to implement sockunion.h, with the + following content: + + NOTE: For better portability, struct sockaddr_storage should be used. + union sockunion is okay, but is not really portable enough. +*/ +union sockunion { + struct sockinet { +#ifdef HAVE_SOCKADDR_LEN + u_char si_len; + u_char si_family; +#else + u_short si_family; +#endif + u_short si_port; + } su_si; + struct sockaddr_in su_sin; +#ifdef INET6 + struct sockaddr_in6 su_sin6; +#endif +}; +#ifdef HAVE_SOCKADDR_LEN +#define su_len su_si.si_len +#endif +#define su_family su_si.si_family +#define su_port su_si.si_port + +#endif /* NEED_SOCKADDR_STORAGE */ --- apache_1.3.28.orig/src/main/getaddrinfo.c Thu Jan 1 01:00:00 1970 +++ apache_1.3.28/src/main/getaddrinfo.c Fri Jul 25 11:01:55 2003 @@ -0,0 +1,162 @@ +/* + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * fake library for ssh v6 enabler patch + * + * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror(). + * These funtions are defined in rfc2133. + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For exapmle, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + * + * In the case not using 'configure --enable-ipv6', this getaddrinfo.c + * will be used if you have broken getaddrinfo or no getaddrinfo. + */ + +#if 0 +#include +#include +#include +#include +#include +#include +#include "gai.h" +#endif + +static struct addrinfo * +malloc_ai(port, addr, socktype, protocol) +int port; +u_long addr; +int socktype; +int protocol; +{ + struct addrinfo *ai; + + if (ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + + sizeof(struct sockaddr_in))) { + memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); + ai->ai_addr = (struct sockaddr *)(ai + 1); +#if defined(HAVE_SOCKADDR_LEN) + ai->ai_addr->sa_len = +#endif + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr->sa_family = ai->ai_family = AF_INET; + ai->ai_socktype = socktype; + ai->ai_protocol = protocol; + ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; + ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; + return ai; + } else { + return NULL; + } +} + +char * +gai_strerror(ecode) +int ecode; +{ + switch (ecode) { + case EAI_NODATA: + return "no address associated with hostname."; + case EAI_MEMORY: + return "memory allocation failure."; + default: + return "unknown error."; + } +} + +void +freeaddrinfo(ai) +struct addrinfo *ai; +{ + struct addrinfo *next; + + do { + next = ai->ai_next; + free(ai); + } while (ai = next); +} + +int +getaddrinfo(hostname, servname, hints, res) +const char *hostname, *servname; +const struct addrinfo *hints; +struct addrinfo **res; +{ + struct addrinfo *cur, *prev = NULL; + struct hostent *hp; + int i, port; + + if (servname) + port = htons(atoi(servname)); + else + port = 0; + if (hints && hints->ai_flags & AI_PASSIVE) + if (*res = malloc_ai(port, htonl(0x00000000), + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM, + (*res)->ai_protocol)) + return 0; + else + return EAI_MEMORY; + if (!hostname) + if (*res = malloc_ai(port, htonl(0x7f000001), + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM, + (*res)->ai_protocol)) + return 0; + else + return EAI_MEMORY; + if (inet_addr(hostname) != -1) + if (*res = malloc_ai(port, inet_addr(hostname), + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM, + (*res)->ai_protocol)) + return 0; + else + return EAI_MEMORY; + if ((hp = gethostbyname(hostname)) && + hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { + for (i = 0; hp->h_addr_list[i]; i++) + if (cur = malloc_ai(port, + ((struct in_addr *)hp->h_addr_list[i])->s_addr, + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM, + (*res)->ai_protocol)) { + if (prev) + prev->ai_next = cur; + else + *res = cur; + prev = cur; + } else { + if (*res) + freeaddrinfo(*res); + return EAI_MEMORY; + } + return 0; + } + return EAI_NODATA; +} --- apache_1.3.28.orig/src/main/getnameinfo.c Thu Jan 1 01:00:00 1970 +++ apache_1.3.28/src/main/getnameinfo.c Fri Jul 25 11:01:55 2003 @@ -0,0 +1,95 @@ +/* + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * fake library for ssh v6 enabler patch + * + * This file includes getnameinfo(). + * These funtions are defined in rfc2133. + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For exapmle, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + * + * In the case not using 'configure --enable-ipv6', this getnameinfo.c + * will be used if you have broken getnameinfo or no getnameinfo. + */ + +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include "gai.h" +#endif + +int +getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) +const struct sockaddr *sa; +size_t salen; +char *host; +size_t hostlen; +char *serv; +size_t servlen; +int flags; +{ + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct hostent *hp; + char tmpserv[16]; + + if (serv) { + sprintf(tmpserv, "%d", ntohs(sin->sin_port)); + if (strlen(tmpserv) > servlen) + return EAI_MEMORY; + else + strcpy(serv, tmpserv); + } + if (host) + if (flags & NI_NUMERICHOST) + if (strlen(inet_ntoa(sin->sin_addr)) > hostlen) + return EAI_MEMORY; + else { + strcpy(host, inet_ntoa(sin->sin_addr)); + return 0; + } + else + if (hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), + AF_INET)) + if (strlen(hp->h_name) > hostlen) + return EAI_MEMORY; + else { + strcpy(host, hp->h_name); + return 0; + } + else + return EAI_NODATA; + return 0; +} --- apache_1.3.28.orig/src/main/http_config.c Fri Jul 25 11:00:49 2003 +++ apache_1.3.28/src/main/http_config.c Fri Jul 25 11:01:55 2003 @@ -1591,7 +1591,6 @@ ap_scoreboard_fname = DEFAULT_SCOREBOARD; ap_lock_fname = DEFAULT_LOCKFILE; ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD; - ap_bind_address.s_addr = htonl(INADDR_ANY); ap_listeners = NULL; ap_listenbacklog = DEFAULT_LISTENBACKLOG; ap_extended_status = 0; @@ -1624,7 +1623,13 @@ 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; @@ -1643,21 +1648,33 @@ 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", + gai_strerror(gai), ap_default_family); + 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); } --- apache_1.3.34/src/main/http_core.c.orig 2005-06-28 20:03:25.000000000 +0200 +++ apache_1.3.34/src/main/http_core.c 2005-10-18 10:14:09.000000000 +0200 @@ -28,6 +28,7 @@ #include "util_md5.h" #include "scoreboard.h" #include "fnmatch.h" +#include "sa_len.h" #ifdef USE_MMAP_FILES #include @@ -570,7 +571,7 @@ * file if you care. So the adhoc value should do. */ return ap_psprintf(r->pool,"%pA%pp%pp%pp%pp", - &r->connection->local_addr.sin_addr, + &((struct sockaddr_in *)&(r->connection->local_addr))->sin_addr, (void *)ap_user_name, (void *)ap_listeners, (void *)ap_server_argv0, @@ -666,7 +667,9 @@ */ 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 */ @@ -678,30 +681,54 @@ 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 +#ifdef INET6 + || res->ai_family == AF_INET6 +#endif + ) + ) + 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; + conn->double_reverse = ok ? 1 : -1; + freeaddrinfo(res0); /* invalidate possible reverse-resolved hostname if forward lookup fails */ - conn->remote_host = ""; + if(!ok) + conn->remote_host = ""; } 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) { @@ -723,10 +750,14 @@ || 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) { @@ -804,6 +835,7 @@ { 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); @@ -813,23 +845,22 @@ } 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; @@ -841,7 +872,7 @@ API_EXPORT(unsigned) ap_get_server_port(const request_rec *r) { unsigned port; - unsigned cport = ntohs(r->connection->local_addr.sin_port); + unsigned cport = ntohs(((struct sockaddr_in *)&r->connection->local_addr)->sin_port); core_dir_config *d = (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); @@ -2647,12 +2678,25 @@ 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; } @@ -2684,48 +2728,71 @@ 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; + 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) { - return "Missing IP address"; - } - else if (ports[1] == '\0') { - return "Address must end in :"; + host = port = NULL; + if (!p) { + port = strrchr(h, ':'); + if (port != NULL) { + if (port == h) { + return "Missing IP address"; + } + else if (port[1] == '\0') { + return "Address must end in :"; + } + *(port++) = '\0'; + if (*h) + host = h; + } + else { + host = NULL; + port = h; } - *(ports++) = '\0'; - } - else { - ports = ips; + } else { + host = h; + port = p; } - 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"; + 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); } - new->local_addr.sin_port = htons((unsigned short)port); + + memcpy(&new->local_addr, res->ai_addr, res->ai_addrlen); + new->fd = -1; new->used = 0; new->next = ap_listeners; @@ -3650,7 +3717,7 @@ { "ThreadStackSize", set_threadstacksize, NULL, RSRC_CONF, TAKE1, "Stack size each created thread will use."}, #endif -{ "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"}, @@ -3684,7 +3751,7 @@ "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" }, #ifdef _OSD_POSIX { "BS2000Account", set_bs2000_account, NULL, RSRC_CONF, TAKE1, --- apache_1.3.28.orig/src/main/http_main.c Fri Jul 25 11:00:49 2003 +++ apache_1.3.28/src/main/http_main.c Fri Jul 25 12:13:12 2003 @@ -124,6 +124,8 @@ #include /* for IRIX, FD_SET calls bzero() */ #endif +#include "sa_len.h" + #ifdef MULTITHREAD /* special debug stuff -- PCS */ @@ -249,7 +251,12 @@ 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}; +#ifdef INET6 +API_VAR_EXPORT int ap_default_family = PF_INET6; +#else +API_VAR_EXPORT int ap_default_family = PF_INET; +#endif +API_VAR_EXPORT struct sockaddr_storage ap_bind_address={0}; 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; @@ -1448,7 +1455,11 @@ fprintf(stderr, "Usage: %s [-D name] [-d directory] [-f file]\n", bin); #endif fprintf(stderr, " %s [-C \"directive\"] [-c \"directive\"]\n", pad); - fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T] [-F]\n", pad); + fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T] [-F]" +#ifdef INET6 + " [-46]" +#endif + "\n", pad); fprintf(stderr, "Options:\n"); #ifdef SHARED_CORE fprintf(stderr, " -R directory : specify an alternate location for shared object files\n"); @@ -1474,6 +1485,10 @@ #ifndef WIN32 fprintf(stderr, " -F : run main process in foreground, for process supervisors\n"); #endif +#ifdef INET6 + fprintf(stderr, " -4 : assume IPv4 on parsing configuration file\n"); + fprintf(stderr, " -6 : assume IPv6 on parsing configuration file\n"); +#endif #ifdef WIN32 fprintf(stderr, " -n name : name the Apache service for -k options below;\n"); fprintf(stderr, " -k stop|shutdown : tell running Apache to shutdown\n"); @@ -3630,11 +3645,13 @@ 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). @@ -3643,17 +3660,29 @@ 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); #ifdef EAPI conn->ctx = ap_ctx_new(conn->pool); #endif /* EAPI */ @@ -3711,21 +3740,47 @@ #define sock_disable_nagle(s, c) /* NOOP */ #endif -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]; + char addr[INET6_ADDRSTRLEN + 128]; + char a0[INET6_ADDRSTRLEN]; + char p0[NI_MAXSERV]; +#ifdef MPE + int privport = 0; +#endif - 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)); + switch(server->sa_family){ + case AF_INET: +#ifdef INET6 + case AF_INET6: +#endif + 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); @@ -3828,15 +3883,19 @@ #ifdef MPE /* MPE requires CAP=PM and GETPRIVMODE to bind to ports less than 1024 */ - if (ntohs(server->sin_port) < 1024) + if (privport) GETPRIVMODE(); #endif - - 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); #ifdef MPE - if (ntohs(server->sin_port) < 1024) + if (privport) GETUSERMODE(); #endif @@ -3849,7 +3908,7 @@ exit(1); } #ifdef MPE - if (ntohs(server->sin_port) < 1024) + if (privport) GETUSERMODE(); #endif @@ -4002,15 +4061,17 @@ 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; @@ -4327,8 +4388,8 @@ 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; /* All of initialization is a critical section, we don't care if we're @@ -4505,7 +4566,7 @@ 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) { @@ -4671,7 +4732,7 @@ */ 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", @@ -4719,8 +4780,8 @@ 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); /* @@ -4875,12 +4936,13 @@ #ifdef _OSD_POSIX /* BS2000 requires a "special" version of fork() before a setuid() call */ - if ((pid = os_fork(ap_user_name)) == -1) { + if ((pid = os_fork(ap_user_name)) == -1) #elif defined(TPF) - if ((pid = os_fork(s, slot)) == -1) { + if ((pid = os_fork(s, slot)) == -1) #else - if ((pid = fork()) == -1) { + if ((pid = fork()) == -1) #endif + { ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process"); /* fork didn't succeed. Fix the scoreboard or else @@ -5497,7 +5559,10 @@ ap_setup_prelinked_modules(); while ((c = getopt(argc, argv, - "D:C:c:xXd:Ff:vVlLR:StTh" + "D:C:c:xXd:Ff:vVlLR:StTh4" +#ifdef INET6 + "6" +#endif #ifdef DEBUG_SIGSTOP "Z:" #endif @@ -5575,8 +5640,14 @@ ap_configtestonly = 1; ap_docrootcheck = 0; break; - case 'h': - usage(argv[0]); + case '4': + ap_default_family = PF_INET; + break; +#ifdef INET6 + case '6': + ap_default_family = PF_INET6; + break; +#endif case '?': usage(argv[0]); } @@ -5665,9 +5736,10 @@ 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. */ @@ -5722,25 +5794,32 @@ #endif 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) { @@ -7447,7 +7526,11 @@ while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLz:Z:wiuStThk:n:W:")) != -1) { #else /* !WIN32 */ - while ((c = getopt(argc, argv, "D:C:c:Xd:Ff:vVlLesStTh")) != -1) { + while ((c = getopt(argc, argv, "D:C:c:Xd:Ff:vVlLesStTh4" +#ifdef INET6 + "6" +#endif + )) != -1) { #endif char **new; switch (c) { @@ -7993,6 +8076,10 @@ case 't': case 'T': case 'h': + case '4': +#ifdef INET6 + case '6': +#endif case '?': break; case 'R': --- apache_1.3.31/src/main/http_vhost.c.orig Mon Mar 29 23:03:25 2004 +++ apache_1.3.31/src/main/http_vhost.c Wed May 12 13:49:13 2004 @@ -25,6 +25,7 @@ #include "http_log.h" #include "http_vhost.h" #include "http_protocol.h" +#include "sa_len.h" /* * After all the definitions there's an explanation of how it's all put @@ -122,78 +123,114 @@ * *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; - } - 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 ((my_addr = ap_inet_addr(w)) != INADDR_NONE) { - 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, "_default4_") == 0 || + ((ap_default_family == PF_INET +#ifndef INET6 + || ap_default_family == PF_UNSPEC +#endif + ) && strcasecmp(w, "_default_") == 0)){ + hoststr = "255.255.255.255"; + hints.ai_family = PF_INET; + } +#ifdef INET6 + 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; +#endif + 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: +#ifdef INET6 + case AF_INET6: +#endif + 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; } @@ -207,7 +244,8 @@ /* 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; @@ -225,10 +263,11 @@ } -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); } @@ -302,6 +341,19 @@ 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); +#ifdef INET6 + case AF_INET6: + return hash_inaddr(((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12]); +#endif + default: + return hash_inaddr(sa->sa_family); + } +} static ipaddr_chain *new_ipaddr_chain(pool *p, @@ -329,25 +381,77 @@ 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; + } +#ifdef INET6 + 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; + } +#endif + default: /*unsupported*/ + break; } } + +#ifdef INET6 + if (sa->sa_family == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr)) { + /* + * This is just horrible. I just hate IPv4 mapped address. It + * complicates access control too much. + * Due to hashed lookup, we need to visit it again. + */ + struct sockaddr_in sin; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; +#ifdef SIN6_LEN + sin.sin_len = sizeof(sin); +#endif + sin.sin_port = ((struct sockaddr_in6 *)sa)->sin6_port; + memcpy(&sin.sin_addr, + &((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12], + sizeof(sin.sin_addr)); + return find_ipaddr((struct sockaddr *)&sin); + } +#endif + return NULL; } @@ -373,21 +477,7 @@ 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 defined for this NameVirtualHost!\n", buf); @@ -515,10 +605,37 @@ * 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; - if (sar->host_addr.s_addr != INADDR_ANY) { + 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; + } +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; + sin6 = (struct sockaddr_in6 *)&sar->host_addr; + if (*(ap_uint32_t *)&sin6->sin6_addr.s6_addr[0] == 0 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[4] == 0 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[8] == 0 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[12] == 0) { + wildcard++; + } + break; + } +#endif + } + + if (!wildcard) { *iphash_table_tail[bucket] = ic; iphash_table_tail[bucket] = &ic->next; } @@ -545,12 +662,45 @@ has_default_vhost_addr = 0; for (sar = s->addrs; sar; sar = sar->next) { ipaddr_chain *ic; + int wildcard; - 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) { + 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; + } +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; + sin6 = (struct sockaddr_in6 *)&sar->host_addr; + if (*(ap_uint32_t *)&sin6->sin6_addr.s6_addr[0] == ~0 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[4] == ~0 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[8] == ~0 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[12] == ~0) { + wildcard++; + } + break; + } +#endif + } + + if (wildcard) { + /* add it to default bucket for each appropriate sar + * since we need to do a port test + */ + ipaddr_chain *other; + + 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); @@ -563,10 +713,11 @@ } 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]; @@ -603,19 +754,33 @@ } 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"); } @@ -663,45 +828,80 @@ const char *src; char *dst; const char *port_str; + const char *u, *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 == '.') - goto bad; - else - continue; - } - if (*src == '/' || *src == '\\') { - goto bad; - } - if (*src == ':') { - port_str = src + 1; - /* check the port part */ - while (*++src) { - if (!ap_isdigit(*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 == ':') { + port_str = v + 1; + v++; + while (*v) { /* check if portnum is correct */ + if (!ap_isdigit(*v++)) goto bad; - } } - if (src[-1] == ':') + if (v[-1] == ':') + goto bad; + else { + /* a known "good" port value */ + int iport; + iport = atoi(port_str); + if (iport < 1 || iport > 65535) { + goto bad; + } + r->parsed_uri.port_str = ap_pstrdup(r->pool, port_str); + r->parsed_uri.port = iport; + } + } + } else { + while (*src) { + if (*src == '.') { + *dst++ = *src++; + if (*src == '.') + goto bad; + else + continue; + } + if (*src == '/' || *src == '\\') { goto bad; - else { - /* a known "good" port value */ - int iport; - iport = atoi(port_str); - if (iport < 1 || iport > 65535) { + } + if (*src == ':') { + port_str = src + 1; + /* sheck the port part */ + while (*++src) { + if (!ap_isdigit(*src)) { + goto bad; + } + } + if (src[-1] == ':') goto bad; + else { + /* a known "good" port value */ + int iport; + iport = atoi(port_str); + if (iport < 1 || iport > 65535) { + goto bad; + } + r->parsed_uri.port_str = ap_pstrdup(r->pool, port_str); + r->parsed_uri.port = iport; } - r->parsed_uri.port_str = ap_pstrdup(r->pool, port_str); - r->parsed_uri.port = iport; - break; } + *dst++ = *src++; } - *dst++ = *src++; } /* strip trailing gubbins */ if (dst > host && dst[-1] == '.') { @@ -716,7 +916,7 @@ 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; } @@ -819,11 +1019,25 @@ * 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; +#ifdef INET6 + case AF_INET6: + port = ntohs(((struct sockaddr_in6 *) + &r->connection->local_addr)->sin6_port); + break; +#endif + default: + port = 0; /*XXX*/ + } last_s = NULL; /* Recall that the name_chain is a list of server_addr_recs, some of @@ -878,7 +1092,22 @@ 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; +#ifdef INET6 + case AF_INET6: + port = ntohs(((struct sockaddr_in6 *) + &r->connection->local_addr)->sin6_port); + break; +#endif + default: + port = 0; /*XXX*/ + } /* * This is in conjunction with the ServerPath code in http_core, so we @@ -938,10 +1167,22 @@ 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; @@ -959,6 +1200,7 @@ return; } +fail: /* otherwise we're stuck with just the main server * and no name-based vhosts */ --- apache_1.3.28.orig/src/main/rfc1413.c Mon Feb 3 18:13:23 2003 +++ apache_1.3.28/src/main/rfc1413.c Fri Jul 25 12:15:05 2003 @@ -82,6 +82,7 @@ #include "http_log.h" /* for aplog_error */ #include "rfc1413.h" #include "http_main.h" /* set_callback_and_alarm */ +#include "sa_len.h" /* Local stuff. */ /* Semi-well-known port */ @@ -109,12 +110,13 @@ /* 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]; @@ -129,16 +131,47 @@ * addresses from the query socket. */ - our_query_sin = *our_sin; - our_query_sin.sin_port = htons(ANY_PORT); -#ifdef MPE - our_query_sin.sin_addr.s_addr = INADDR_ANY; +#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 - rmt_query_sin = *rmt_sin; - rmt_query_sin.sin_port = htons(RFC1413_PORT); + switch (our_sin->sa_family) { + case AF_INET: +#ifdef MPE + ((struct sockaddr_in *)&our_query_sin)->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(??) */ +#endif + ((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; +#ifdef INET6 + case AF_INET6: +#ifdef MPE + memcpy(&((struct sockaddr_in6 *)&our_query_sin)->sin6_addr, + &in6addr_any, sizeof(struct in6_addr)); +#endif + ((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; +#endif + 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; @@ -149,12 +182,18 @@ * 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. */ #ifdef CHARSET_EBCDIC @@ -219,9 +258,9 @@ ascii2ebcdic(buffer, buffer, (size_t)i); #endif 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 @@ -243,7 +282,7 @@ 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"); @@ -256,8 +295,10 @@ 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); --- apache_1.3.28.orig/src/main/util.c Mon Feb 3 18:13:23 2003 +++ apache_1.3.28/src/main/util.c Fri Jul 25 11:01:55 2003 @@ -2017,52 +2017,87 @@ * Parses a host of the form
[:port] * :port is permitted if 'port' is not NULL */ -API_EXPORT(unsigned long) ap_get_virthost_addr(char *w, unsigned short *ports) +API_EXPORT(struct sockaddr *) ap_get_virthost_addr(char *w, unsigned short *ports) { - struct hostent *hep; - unsigned long my_addr; - char *p; - - p = strchr(w, ':'); + 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; } @@ -2090,7 +2125,8 @@ #endif char str[MAXHOSTNAMELEN]; char *server_hostname = NULL; - struct hostent *p; + struct addrinfo hints, *res; + int error; #ifdef BEOS /* BeOS returns zero as an error for gethostname */ if (gethostname(str, sizeof(str) - 1) == 0) { @@ -2103,29 +2139,38 @@ } else { - str[sizeof(str) - 1] = '\0'; - if ((!(p = gethostbyname(str))) - || (!(server_hostname = find_fqdn(a, p)))) { - /* Recovery - return the default servername by IP: */ - if (p && p->h_addr_list && 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 */ - } - } - else - /* Since we found a fqdn, return it with no logged message. */ - return server_hostname; - } - - /* If we don't have an fdqn or IP, fall back to the loopback addr */ - if (!server_hostname) - server_hostname = ap_pstrdup(a, "127.0.0.1"); - - ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, NULL, - "%s: Could not determine the server's fully qualified " - "domain name, using %s for ServerName", - ap_server_argv0, server_hostname); + str[sizeof(str) - 1] = '\0'; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_flags = AI_CANONNAME; + error = getaddrinfo(str, NULL, &hints, &res); + if (error) + { + /* Recovery - return the default servername by IP: */ + + fprintf(stderr, "%s: cannot determine local host name.\n", + ap_server_argv0); + fprintf(stderr, "Use the ServerName directive to set it manually.\n"); + exit(1); + + server_hostname = ap_pstrdup(a, res->ai_canonname); + } + else if (1) /*fqdn found*/ + { + /* XXX should check more conditions */ + server_hostname = ap_pstrdup(a, res->ai_canonname); + } + else + { + ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, NULL, + "%s: Could not determine the server's fully qualified " + "domain name, using %s for ServerName", + ap_server_argv0, server_hostname); + } + + /* Since we found a fdqn, return it with no logged message. */ + freeaddrinfo(res); + } return server_hostname; } @@ -2369,3 +2414,11 @@ } *dest = 0; } + +#ifdef NEED_GETADDRINFO +#include "getaddrinfo.c" +#endif + +#ifdef NEED_GETNAMEINFO +#include "getnameinfo.c" +#endif --- apache_1.3.28.orig/src/main/util_script.c Mon Feb 3 18:13:23 2003 +++ apache_1.3.28/src/main/util_script.c Fri Jul 25 11:01:55 2003 @@ -67,6 +67,7 @@ #include "http_request.h" /* for sub_req_lookup_uri() */ #include "util_script.h" #include "util_date.h" /* For parseHTTPdate() */ +#include "sa_len.h" #ifdef OS2 #define INCL_DOS @@ -203,6 +204,7 @@ 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 @@ -294,8 +296,16 @@ 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); --- apache_1.3.28.orig/src/main/util_uri.c Mon Feb 3 18:13:24 2003 +++ apache_1.3.28/src/main/util_uri.c Fri Jul 25 11:01:55 2003 @@ -424,6 +424,12 @@ * the hostname. If there's a port it is the first colon. */ s = memchr(hostinfo, ':', uri - hostinfo); + 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); @@ -480,7 +486,12 @@ /* 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; } --- apache_1.3.28.orig/src/modules/proxy/mod_proxy.c Fri Jul 25 11:00:49 2003 +++ apache_1.3.28/src/modules/proxy/mod_proxy.c Fri Jul 25 11:01:55 2003 @@ -574,11 +574,31 @@ 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, ':'); + 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)"; @@ -589,7 +609,7 @@ *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; @@ -602,7 +622,7 @@ new = ap_push_array(conf->proxies); new->scheme = f; new->protocol = r; - new->hostname = p + 3; + new->hostname = bl; new->port = port; return NULL; } --- apache_1.3.28.orig/src/modules/proxy/mod_proxy.h Mon Feb 3 18:13:26 2003 +++ apache_1.3.28/src/modules/proxy/mod_proxy.h Fri Jul 25 11:01:55 2003 @@ -310,7 +310,7 @@ 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); --- apache_1.3.28.orig/src/modules/proxy/proxy_connect.c Mon Feb 3 18:13:26 2003 +++ apache_1.3.28/src/modules/proxy/proxy_connect.c Fri Jul 25 11:27:12 2003 @@ -113,14 +113,15 @@ 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 = @@ -128,27 +129,59 @@ 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); + 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) { + 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] == '*') + for (res = res0; res; res = res = res->ai_next) { + struct sockaddr_in *sin; + int fail; + + fail = 0; + for (i = 0; i < conf->noproxies->nelts; i++) { + if (npent[i].name != NULL && strstr(hoststr, npent[i].name)) + fail++; + if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0) + fail++; + 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) { + freeaddrinfo(res0); return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); + } } /* Check if it is an allowed port */ @@ -159,34 +192,42 @@ case DEFAULT_SNEWS_PORT: break; default: + freeaddrinfo(res0); return HTTP_FORBIDDEN; } } - else if (!allowed_port(conf, port)) + else if (!allowed_port(conf, port)) { + freeaddrinfo(res0); return HTTP_FORBIDDEN; + } if (proxyhost) { + char pbuf[10]; + + 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); } 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); - - if (err != NULL) - return ap_proxyerror(r, - proxyhost ? HTTP_BAD_GATEWAY : HTTP_INTERNAL_SERVER_ERROR, err); - - 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; - } + sock = i = -1; + for (res = res0; res; res = res->ai_next) { + sock = ap_psocket_ex(r->pool, res->ai_family, res->ai_socktype, res->ai_protocol, 1); + if (sock == -1) + continue; #ifdef CHECK_FD_SETSIZE if (sock >= FD_SETSIZE) { @@ -196,19 +237,15 @@ "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; + continue; } #endif - 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); + i = ap_proxy_doconnect(sock, res->ai_addr, r); if (i == 0) break; - j++; } + freeaddrinfo(res0); if (i == -1) { ap_pclosesocket(r->pool, sock); return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, ap_pstrcat(r->pool, --- apache_1.3.28.orig/src/modules/proxy/proxy_ftp.c Mon Feb 3 18:13:26 2003 +++ apache_1.3.28/src/modules/proxy/proxy_ftp.c Fri Jul 25 11:18:38 2003 @@ -62,6 +62,7 @@ #include "http_main.h" #include "http_log.h" #include "http_core.h" +#include "sa_len.h" #define AUTODETECT_PWD @@ -555,8 +556,10 @@ const char *err; int port, 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; @@ -577,11 +580,18 @@ 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; +/* 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]; char *size = NULL; @@ -658,62 +668,50 @@ 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", destport); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(desthost, 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) { + sock = ap_psocket_ex(p, res->ai_family, res->ai_socktype, + res->ai_protocol, 1); + if (sock == -1) + continue; + #if !defined(TPF) && !defined(BEOS) - if (conf->recv_buffer_size > 0 - && 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"); - } + if (conf->recv_buffer_size > 0 + && 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"); + } #endif - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, - sizeof(one)) == -1) { + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, + sizeof(one)) == -1) { #ifndef _OSD_POSIX /* BS2000 has this option "always on" */ - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "proxy: error setting reuseaddr option: setsockopt(SO_REUSEADDR)"); - ap_pclosesocket(p, sock); - return HTTP_INTERNAL_SERVER_ERROR; + 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; #endif /* _OSD_POSIX */ - } - -#ifdef SINIX_D_RESOLVER_BUG - { - struct in_addr *ip_addr = (struct in_addr *)*server_hp.h_addr_list; - - for (; ip_addr->s_addr != 0; ++ip_addr) { - memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr)); - i = ap_proxy_doconnect(sock, &server, r); - if (i == 0) - break; } - } -#else - 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); } -#endif + 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, @@ -944,7 +942,7 @@ } /* try to set up PASV data connection first */ - 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, @@ -961,11 +959,22 @@ } #endif - 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); + Explain0("FTP: passive command issued"); ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PASV command issued"); -/* possible results: 227, 421, 500, 501, 502, 530 */ +/* possible results: 227, 228, 229, 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. */ @@ -976,7 +985,7 @@ 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")); + ap_psprintf(p, "proxy: %s: control connection is toast", cmd))); } else { pasv[i - 1] = '\0'; @@ -1004,10 +1013,14 @@ 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, @@ -1017,6 +1030,64 @@ 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) { + return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, + 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) { + return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, + 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 */ @@ -1025,14 +1096,14 @@ } 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, @@ -1048,13 +1119,28 @@ #endif /* _OSD_POSIX */ } - 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_psprintf(p, "proxy: error binding to ftp data socket %s:%s", + hostnamebuf, portnamebuf))); } listen(dsock, 2); /* only need a short queue */ } @@ -1308,7 +1394,7 @@ 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); --- apache_1.3.34/src/modules/proxy/proxy_http.c.orig 2005-10-18 09:56:15.000000000 +0200 +++ apache_1.3.34/src/modules/proxy/proxy_http.c 2005-10-18 10:15:06.000000000 +0200 @@ -113,9 +113,8 @@ 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; + struct addrinfo hints, *res, *res0; + int error; BUFF *f; char buffer[HUGE_STRING_LEN]; char portstr[32]; @@ -141,9 +140,6 @@ 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, "://"); @@ -151,6 +147,8 @@ return HTTP_BAD_REQUEST; urlptr += 3; destport = DEFAULT_HTTP_PORT; + ap_snprintf(portstr, sizeof(portstr), "%d", DEFAULT_HTTP_PORT); + destportstr = portstr; #ifdef EAPI ap_hook_use("ap::mod_proxy::http::handler::set_destport", AP_HOOK_SIG2(int,ptr), @@ -169,7 +167,20 @@ 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 = strchr(desthost, ':'); if (strp2 != NULL) { *(strp2++) = '\0'; @@ -179,46 +190,71 @@ } } + 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) { + 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(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))) + for (res = res0; res; res = res->ai_next) { + struct sockaddr_in *sin; +#ifdef INET6 + struct sockaddr_in6 *sin6; +#endif + int fail; + + fail = 0; + for (i = 0; i < conf->noproxies->nelts; i++) { + if (npent[i].name != NULL && strstr(desthost, npent[i].name)) + fail++; + if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0) + fail++; + 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) { + 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) + char pbuf[10]; + + 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 */ #ifdef EAPI peer = ap_psprintf(p, "%s:%u", proxyhost, proxyport); #endif } - 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); -#ifdef EAPI - peer = ap_psprintf(p, "%s:%u", desthost, destport); -#endif - } - /* * 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; - } + sock = i = -1; + for (res = res0; res; res = res->ai_next) { + sock = ap_psocket_ex(p, res->ai_family, res->ai_socktype, res->ai_protocol, 1); + if (sock < 0) + continue; #if !defined(TPF) && !defined(BEOS) if (conf->recv_buffer_size) { @@ -231,38 +267,13 @@ } #endif -#ifdef SINIX_D_RESOLVER_BUG - { - struct in_addr *ip_addr = (struct in_addr *)*server_hp.h_addr_list; - - for (; ip_addr->s_addr != 0; ++ip_addr) { - memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr)); - i = ap_proxy_doconnect(sock, &server, r); - if (i == 0) - break; - /* - * Even if the connection was unsuccesful we should - * reinit the socket - */ - sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1); - } - } -#else - 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); + i = ap_proxy_doconnect(sock, res->ai_addr, r); if (i == 0) break; - /* - * Even if the connection was unsuccesful we should - * reinit the socket - */ - sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1); + ap_pclosesocket(p, sock); j++; } -#endif + freeaddrinfo(res0); if (i == -1) { if (proxyhost != NULL) return DECLINED; /* try again another way */ @@ -591,17 +602,30 @@ ap_table_set(resp_hdrs, "Content-Location", proxy_location_reverse_map(r, urlstr)); /* check if NoCache directive on this host */ + { + struct sockaddr_in *sin; +#ifdef INET6 + struct sockaddr_in6 *sin6; +#endif + 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; + 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 --- apache_1.3.28.orig/src/modules/proxy/proxy_util.c Mon Feb 3 18:13:26 2003 +++ apache_1.3.28/src/modules/proxy/proxy_util.c Fri Jul 25 11:01:55 2003 @@ -64,6 +64,7 @@ #include "http_log.h" #include "util_uri.h" #include "util_date.h" /* get ap_checkmask() decl. */ +#include "sa_len.h" static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r); static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r); @@ -219,6 +220,7 @@ 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"; @@ -257,11 +259,22 @@ *passwordp = password; } - strp = strrchr(host, ':'); - if (strp != NULL) { - *(strp++) = '\0'; - - for (i = 0; strp[i] != '\0'; i++) + 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; @@ -280,17 +293,29 @@ return "Missing host in URL"; /* check hostname syntax */ for (i = 0; host[i] != '\0'; i++) - if (!ap_isdigit(host[i]) && host[i] != '.') + if (!ap_isdigit(host[i]) && host[i] != '.' && host[i] != ':') break; /* must be an IP address */ #if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS) if (host[i] == '\0' && (inet_addr(host) == -1)) + return "Bad IP address in URL"; +#else + 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 - if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1)) + return "Bad IP address in URL"; #endif - { - return "Bad IP address in URL"; + } + freeaddrinfo(res0); } +#endif /* if (strchr(host,'.') == NULL && domain != NULL) host = pstrcat(p, host, domain, NULL); @@ -1359,22 +1384,46 @@ 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); #if defined(WIN32) || defined(NETWARE) if (i == SOCKET_ERROR) errno = WSAGetLastError(); #endif /* WIN32 */ } 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)); + hbuf, pbuf); } ap_kill_timeout(r); --- apache_1.3.31/src/modules/standard/mod_access.c.orig Sun Mar 7 22:47:14 2004 +++ apache_1.3.31/src/modules/standard/mod_access.c Sat May 15 00:05:40 2004 @@ -31,7 +31,10 @@ T_ALL, T_IP, T_HOST, - T_FAIL + T_FAIL, +#ifdef INET6 + T_IP6, +#endif }; typedef struct { @@ -42,6 +45,12 @@ struct in_addr net; struct in_addr mask; } ip; +#ifdef INET6 + struct { + struct in6_addr net6; + struct in6_addr mask6; + } ip6; +#endif } x; enum allowdeny_type type; } allowdeny; @@ -124,94 +133,242 @@ } 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; +#ifdef INET6 + case AF_INET6: + a->type = T_IP6; + memcpy(&a->x.ip6.net6, &((struct sockaddr_in6 *)&net)->sin6_addr, + sizeof(a->x.ip6.net6)); + break; +#endif + 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; - } - if (*t == '.') { - *t++ = 0; + return "network/netmask resolved to multiple addresses"; } - 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; +#ifdef INET6 + case T_IP6: + memcpy(&a->x.ip6.mask6, + &((struct sockaddr_in6 *)&mask)->sin6_addr, + sizeof(a->x.ip6.mask6)); + break; +#endif } - 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; +#ifdef INET6 + 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; + } +#endif } - 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 = ntohl(a->x.ip.net.s_addr); - a->x.ip.mask.s_addr = ntohl(a->x.ip.mask.s_addr); + /* mask network address */ + switch (a->type) { + case T_IP: + a->x.ip.net.s_addr &= a->x.ip.mask.s_addr; + break; + case T_IP6: + a->x.ip6.net6.s6_addr32[0] &= a->x.ip6.mask6.s6_addr32[0]; + a->x.ip6.net6.s6_addr32[1] &= a->x.ip6.mask6.s6_addr32[1]; + a->x.ip6.net6.s6_addr32[2] &= a->x.ip6.mask6.s6_addr32[2]; + a->x.ip6.net6.s6_addr32[3] &= a->x.ip6.mask6.s6_addr32[3]; + } } 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 |= (unsigned int)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; +#ifdef INET6 + 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; +#endif + default: + a->type = T_FAIL; + return "unknown address family for network"; + } + } return NULL; } @@ -275,13 +432,63 @@ 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; +#ifdef INET6 + case AF_INET6: + if (!IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr)) /*XXX*/ + break; + if ((*(ap_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; +#endif } break; +#ifdef INET6 + 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; + } +#endif case T_HOST: if (!gothost) { remotehost = ap_get_remote_host(r->connection, r->per_dir_config, --- apache_1.3.28.orig/src/modules/standard/mod_unique_id.c Mon Feb 3 18:13:30 2003 +++ apache_1.3.28/src/modules/standard/mod_unique_id.c Fri Jul 25 11:01:55 2003 @@ -67,10 +67,22 @@ #include "http_config.h" #include "http_log.h" #include "multithread.h" +#include "sa_len.h" + +/*#define SHORT_UNIQUE_ID*/ typedef struct { unsigned int stamp; - unsigned int in_addr; + union { + struct in_addr in; +#ifdef INET6 +# ifdef SHORT_UNIQUE_ID + ap_uint32_t in6; +# else + struct in6_addr in6; +# endif +#endif + } addr; unsigned int pid; #ifdef MULTITHREAD unsigned int tid; @@ -142,7 +154,7 @@ * this shouldn't be a problem till year 2106. */ -static unsigned global_in_addr; +static struct sockaddr_storage global_addr; #ifdef WIN32 @@ -221,7 +233,8 @@ #define MAXHOSTNAMELEN 256 #endif char str[MAXHOSTNAMELEN + 1]; - struct hostent *hent; + struct addrinfo hints, *res, *res0; + int error; #ifndef NO_GETTIMEOFDAY struct timeval tv; #endif @@ -232,8 +245,8 @@ */ 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); #ifdef MULTITHREAD @@ -269,17 +282,44 @@ } 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: +#ifdef INET6 + case AF_INET6: +#endif + 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 @@ -336,7 +376,23 @@ "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; + break; +#ifdef INET6 + 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; +#endif + } /* * If we use 0 as the initial counter we have a little less protection --- apache_1.3.28.orig/src/support/ab.c Sun Jul 6 19:52:27 2003 +++ apache_1.3.28/src/support/ab.c Fri Jul 25 11:01:55 2003 @@ -158,6 +158,8 @@ #include #endif +#include "sa_len.h" + #endif /* NO_APACHE_INCLUDES */ #ifdef USE_SSL @@ -246,7 +248,7 @@ char servername[1024]; /* name that server reports */ char hostname[1024]; /* host name */ char proxyhost[1024]; /* proxy host name */ -int proxyport = 0; /* proxy port */ +char *proxyport = NULL; /* proxy port */ int isproxy = 0; char path[1024]; /* path name */ char postfile[1024]; /* name of file containing post data */ @@ -262,7 +264,7 @@ auth[1024], /* optional (basic/uuencoded) * authentification */ hdrs[4096]; /* optional arbitrary headers */ -int port = 80; /* port number */ +char *port = "80"; /* port number */ int use_html = 0; /* use html in the report */ char *tablestring; @@ -299,7 +301,7 @@ struct data *stats; /* date for each request */ fd_set readbits, writebits; /* bits for select */ -struct sockaddr_in server; /* server addr structure */ +struct sockaddr_storage server; /* server addr structure */ #ifndef BEOS #define ab_close(s) close(s) @@ -525,7 +527,7 @@ printf("\r \r"); printf("Server Software: %s\n", servername); printf("Server Hostname: %s\n", hostname); - printf("Server Port: %d\n", port); + printf("Server Port: %s\n", port); printf("\n"); printf("Document Path: %s\n", path); printf("Document Length: %d bytes\n", doclen); @@ -878,7 +880,7 @@ c->cbx = 0; c->gotheader = 0; - c->fd = socket(AF_INET, SOCK_STREAM, 0); + c->fd = socket(server.ss_family, SOCK_STREAM, 0); if (c->fd < 0) { what = "SOCKET"; goto _bad; @@ -895,7 +897,12 @@ again: gettimeofday(&c->start, 0); - if (connect(c->fd, (struct sockaddr *) & server, sizeof(server)) < 0) { +#ifndef SIN6_LEN + if (connect(c->fd, (struct sockaddr *) & server, SA_LEN((struct sockaddr*)&server)) < 0) +#else + if (connect(c->fd, (struct sockaddr *) & server, server.ss_len) < 0) +#endif + { if (errno != EINPROGRESS) { what = "CONNECT"; goto _bad; @@ -1189,7 +1196,7 @@ struct timeval timeout, now; fd_set sel_read, sel_except, sel_write; long i; - int connectport; + char * connectport; char * connecthost; char * url_on_request; @@ -1232,17 +1239,21 @@ } { /* get server information */ - struct hostent *he; - he = gethostbyname(connecthost); - if (!he) { - char theerror[1024]; - ap_snprintf(theerror, sizeof(theerror), - "Bad hostname: %s\n", connecthost); - err(theerror); - } - server.sin_family = he->h_addrtype; - server.sin_port = htons(connectport); - server.sin_addr.s_addr = ((unsigned long *) (he->h_addr_list[0]))[0]; + struct addrinfo hints, *res; + int error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(connecthost, connectport, &hints, &res); + if (error) { + char *theerror=malloc(strlen(connecthost)+16); + sprintf(theerror, "Bad hostname: %s\n", connecthost); + err(theerror); + free(theerror); + } + memcpy(&server, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); } con = malloc(concurrency * sizeof(struct connection)); @@ -1430,7 +1441,7 @@ if (strlen(purl) > 8 && strncmp(purl, "https://", 8) == 0) { purl += 8; ssl = 1; - port = 443; + port = "443"; } #else if (strlen(purl) > 8 && strncmp(purl, "https://", 8) == 0) { @@ -1451,15 +1462,15 @@ *cp = '\0'; strcpy(hostname, h); if (p != NULL) - port = atoi(p); + port = strdup(p); if (( #ifdef USE_SSL - (ssl != 0) && (port != 443)) || ((ssl == 0) && + (ssl != 0) && (strcmp(port, "443"))) || ((ssl == 0) && #endif - (port != 80))) + (strcmp(port, "80")))) { - ap_snprintf(colonport,sizeof(colonport),":%d",port); + ap_snprintf(colonport,sizeof(colonport),":%s",port); } else { colonport[0] = '\0'; } @@ -1622,7 +1633,7 @@ if ((p = strchr(optarg, ':'))) { *p = '\0'; p++; - proxyport = atoi(p); + proxyport = strdup(p); }; strcpy(proxyhost, optarg); isproxy = 1; @@ -1705,3 +1716,7 @@ exit(0); } + +#ifdef NEED_GETADDRINFO +#include "../main/getaddrinfo.c" +#endif --- apache_1.3.28.orig/src/support/logresolve.c Wed May 23 00:52:21 2001 +++ apache_1.3.28/src/support/logresolve.c Fri Jul 25 11:01:55 2003 @@ -54,7 +54,9 @@ #endif /* BEOS */ #endif /* !MPE && !WIN32*/ -static void cgethost(struct in_addr ipnum, char *string, int check); +#include "sa_len.h" + +static void cgethost(struct sockaddr *sa, char *string, int check); static int getline(char *s, int n); static void stats(FILE *output); @@ -91,7 +93,7 @@ */ struct nsrec { - struct in_addr ipnum; + struct sockaddr_storage addr; char *hostname; int noname; struct nsrec *next; @@ -122,17 +124,48 @@ * 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) { + ap_uint32_t hashval; + struct sockaddr_in *sin; +#ifdef INET6 + struct sockaddr_in6 *sin6; +#endif 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; +#ifdef INET6 + case AF_INET6: + hashval = *(ap_uint32_t *)&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12]; + break; +#endif + 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++; @@ -145,45 +178,55 @@ *current = new; new->next = NULL; - new->ipnum = ipnum; +#ifndef SIN6_LEN + memcpy(&new->addr, sa, SA_LEN(sa)); +#else + memcpy(&new->addr, sa, sa->sa_len); +#endif - 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]++; + 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; @@ -211,6 +254,7 @@ 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"; @@ -242,7 +286,14 @@ for (i = 0; i < BUCKETS; i++) for (current = nscache[i]; current != NULL; current = current->next) { - ipstring = inet_ntoa(current->ipnum); + getnameinfo((struct sockaddr *)¤t->addr, +#ifndef SIN6_LEN + SA_LEN((struct sockaddr *)¤t->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); @@ -276,9 +327,10 @@ 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; #ifdef WIN32 WSADATA wsaData; @@ -322,8 +374,10 @@ 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); @@ -333,11 +387,12 @@ 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); } #ifdef WIN32 @@ -358,3 +413,11 @@ return (0); } + +#ifdef NEED_GETADDRINFO +#include "../main/getaddrinfo.c" +#endif + +#ifdef NEED_GETNAMEINFO +#include "../main/getnameinfo.c" +#endif --- apache_1.3.28/src/modules/standard/mod_usertrack.c.orig Mon Feb 3 18:13:30 2003 +++ apache_1.3.28/src/modules/standard/mod_usertrack.c Fri Jul 25 13:13:43 2003 @@ -162,7 +162,7 @@ long reqtime = (long) r->request_time; long clocktime; - unsigned long ipaddr = ntohl(r->connection->remote_addr.sin_addr.s_addr); + unsigned long ipaddr = ntohl(((struct sockaddr_in*)&r->connection->remote_addr)->sin_addr.s_addr); 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); --- apache_1.3.31/src/modules/standard/mod_rewrite.c.orig Wed May 12 14:57:09 2004 +++ apache_1.3.31/src/modules/standard/mod_rewrite.c Wed May 12 15:40:04 2004 @@ -48,6 +48,7 @@ #include "mod_rewrite.h" +#include "sa_len.h" #ifndef NO_WRITEV #ifndef NETWARE @@ -3651,8 +3652,19 @@ result = r->connection->remote_ip; } else if (strcasecmp(var, "REMOTE_PORT") == 0) { - return ap_psprintf(r->pool, "%d", - ntohs(r->connection->remote_addr.sin_port)); + char servbuf[NI_MAXSERV]; + servbuf[0] = '\0'; + if (!getnameinfo((struct sockaddr *)&r->connection->remote_addr, +#ifndef HAVE_SOCKADDR_LEN + SA_LEN((struct sockaddr *)&r->connection->remote_addr), +#else + r->connection->remote_addr.ss_len, +#endif + NULL, 0, servbuf, sizeof(servbuf), NI_NUMERICSERV)) { + return ap_pstrdup(r->pool, servbuf); + } else { + return ap_pstrdup(r->pool, ""); + } } else if (strcasecmp(var, "REMOTE_HOST") == 0) { result = (char *)ap_get_remote_host(r->connection,