Index: apache13/README.v6
diff -c /dev/null apache13/README.v6:1.7
*** /dev/null	Mon Mar 29 00:54:50 1999
--- apache13/README.v6	Mon Mar 29 00:45:30 1999
***************
*** 0 ****
--- 1,99 ----
+ IPv6-ready apache 1.3.x
+ KAME Project
+ $Id: README.v6,v 1.7 1999/03/28 15:45:30 itojun Exp $
+ 
+ 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
+ 
+ 	The above two can be used, for example, to disambiguate
+ 	"BindAddress *".
+ 
+ base commands:
+     Listen
+ 	Listen is expanded to take one more two arguments.
+ 		Listen port
+ 		Listen address:port
+ 		Listen address port
+ 	This is to let you specify "Listen :: 80", since "Listen :::80"
+ 	won't work.
+ 
+ mod_access:
+     deny from
+     allow from
+ 	"deny from " and "allow from" supports IPv6 addresses, under the
+ 	following forms:
+ 		{deny,allow} from v6addr
+ 		{deny,allow} from v6addr/v6mask
+ 		{deny,allow} from v6addr/prefixlen
+ 	Also, wildcard ("*") and string hostname matches IPv6 hosts as well.
+ 
+ mod_proxy:
+     ProxyRequests on
+ 	http/ftp proxying for both IPv4 and IPv6 is possible.
+ 	Access control functions (NoProxy) are not updated yet.
+ 
+ 	NOTE: for security reasons, we recommend you to filter out
+ 	outsider's access to your proxy, by directives like below:
+ 		<Directory proxy:*>
+ 		order deny,allow
+ 		deny from all
+ 		allow from 10.0.0.0/8
+ 		allow from 3ffe:9999:8888:7777::/64
+ 		</Directory>
+ 
+ virtual host:
+     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.
+ 
+     VirtualHost
+ 	<VirtualHost> takes two arguments too.
+ 
+ logresolve (src/support)
+ 	error statistics in nameserver cache code is omitted.
+ 
+ Modules known to be incompatible with IPv6
+ 	mod_unique_id
+ 
+ configure
+ 	Configure has extra option, --enable-rule=INET6.  if the option
+ 	is specified, IPv6 code will be enabled.
+ 
+ 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.
+ 
+ When compiling this kit onto IPv6, you may need to specify some additional
+ library paths or cpp defs. (like -linet6 or -DINET6)
+ --enable-rule=INET6 will give you some warning, 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.kame-v6 for convenience.
+ 
+ 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.
+ 
+ Author contacts
+ 	http://www.kame.net/
+ 	mailto:core@kame.net
Index: apache13/configure.kame-v6
diff -c /dev/null apache13/configure.kame-v6:1.5
*** /dev/null	Mon Mar 29 00:54:51 1999
--- apache13/configure.kame-v6	Sun Jan 17 13:25:32 1999
***************
*** 0 ****
--- 1,3 ----
+ #! /bin/sh
+ 
+ ./configure --enable-rule=INET6 --enable-module=proxy $*
Index: apache13/conf/httpd.conf-dist
diff -c apache13/conf/httpd.conf-dist:1.1.1.4 apache13/conf/httpd.conf-dist:1.6
*** apache13/conf/httpd.conf-dist:1.1.1.4	Thu Mar 25 03:15:26 1999
--- apache13/conf/httpd.conf-dist	Thu Mar 25 04:07:12 1999
***************
*** 170,175 ****
--- 170,180 ----
  #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
Index: apache13/src/Configuration.tmpl
diff -c apache13/src/Configuration.tmpl:1.1.1.2 apache13/src/Configuration.tmpl:1.5
*** apache13/src/Configuration.tmpl:1.1.1.2	Tue Jan 12 13:33:19 1999
--- apache13/src/Configuration.tmpl	Sun Jan 17 13:25:34 1999
***************
*** 160,171 ****
--- 160,175 ----
  #  is performing this function. If PARANOID is set to yes, it will
  #  actually print-out the code that the modules execute
  #
+ # INET6:
+ #  IPv6 support.
+ #
  
  Rule SOCKS4=no
  Rule SOCKS5=no
  Rule IRIXNIS=no
  Rule IRIXN32=yes
  Rule PARANOID=no
+ Rule INET6=no
  
  # The following rules should be set automatically by Configure. However, if
  # they are not set by Configure (because we don't know the correct value for
Index: apache13/src/Configure
diff -c apache13/src/Configure:1.1.1.4 apache13/src/Configure:1.3
*** apache13/src/Configure:1.1.1.4	Thu Mar 25 03:12:34 1999
--- apache13/src/Configure	Thu Mar 25 04:03:03 1999
***************
*** 224,229 ****
--- 224,230 ----
  RULE_PARANOID=`./helpers/CutRule PARANOID $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
***************
*** 1368,1373 ****
--- 1369,1403 ----
  	    LIBS="$LIBS -lresolv"
  	    ;;
      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"
+     if [ -f /usr/include/netinet6/in6.h -a "x`egrep '__KAME__' /usr/include/netinet6/in6.h`" != "x" ]; then
+ 	if [ "x`egrep '^EXTRA_L' Makefile.config | grep linet6`" = "x" ]; then
+ 	    LIBS="$LIBS -L/usr/local/v6/lib -linet6"
+ 	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
  
  ####################################################################
Index: apache13/src/ap/ap_snprintf.c
diff -c apache13/src/ap/ap_snprintf.c:1.1.1.2 apache13/src/ap/ap_snprintf.c:1.4
*** apache13/src/ap/ap_snprintf.c:1.1.1.2	Tue Jan 12 13:33:35 1999
--- apache13/src/ap/ap_snprintf.c	Tue Jan 12 14:29:19 1999
***************
*** 425,430 ****
--- 425,458 ----
  
  
  
+ #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;
+ 
+     if (getnameinfo(sa, sa->sa_len, hostnamebuf, sizeof(hostnamebuf),
+ 	    portnamebuf, sizeof(portnamebuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
+ 	strcpy(hostnamebuf, "???");
+ 	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
***************
*** 871,876 ****
--- 899,905 ----
  		    /* 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 *);
***************
*** 879,884 ****
--- 908,923 ----
  			    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;
Index: apache13/src/include/ap.h
diff -c apache13/src/include/ap.h:1.1.1.2 apache13/src/include/ap.h:1.4
*** apache13/src/include/ap.h:1.1.1.2	Tue Jan 12 13:33:47 1999
--- apache13/src/include/ap.h	Tue Jan 12 14:29:21 1999
***************
*** 86,92 ****
   * 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
   * %pp  takes a void * and outputs it in hex
   *
   * The %p hacks are to force gcc's printf warning code to skip
--- 86,93 ----
   * 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 * 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
Index: apache13/src/include/ap_config.h
diff -c apache13/src/include/ap_config.h:1.1.1.4 apache13/src/include/ap_config.h:1.8
*** apache13/src/include/ap_config.h:1.1.1.4	Thu Mar 25 03:13:13 1999
--- apache13/src/include/ap_config.h	Thu Mar 25 04:03:05 1999
***************
*** 1286,1291 ****
--- 1286,1337 ----
  #define ap_wait_t int
  #endif
  
+ #ifndef INET6
+ #define sockaddr_storage	sockaddr
+ #define ss_family		sa_family
+ #define ss_len			sa_len
+ #endif
+ 
+ #if defined(NEED_GETADDRINFO) || defined(NEED_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
Index: apache13/src/include/http_conf_globals.h
diff -c apache13/src/include/http_conf_globals.h:1.1.1.2 apache13/src/include/http_conf_globals.h:1.4
*** apache13/src/include/http_conf_globals.h:1.1.1.2	Tue Jan 12 13:33:59 1999
--- apache13/src/include/http_conf_globals.h	Tue Jan 12 14:29:23 1999
***************
*** 76,82 ****
  extern int ap_max_requests_per_child;
  extern int ap_threads_per_child;
  extern int ap_excess_requests_per_child;
! extern struct in_addr ap_bind_address;
  extern listen_rec *ap_listeners;
  extern int ap_daemons_to_start;
  extern int ap_daemons_min_free;
--- 76,83 ----
  extern int ap_max_requests_per_child;
  extern int ap_threads_per_child;
  extern int ap_excess_requests_per_child;
! extern struct sockaddr_storage ap_bind_address;
! extern int ap_default_family;
  extern listen_rec *ap_listeners;
  extern int ap_daemons_to_start;
  extern int ap_daemons_min_free;
Index: apache13/src/include/http_vhost.h
diff -c apache13/src/include/http_vhost.h:1.1.1.2 apache13/src/include/http_vhost.h:1.2
*** apache13/src/include/http_vhost.h:1.1.1.2	Tue Jan 12 13:34:08 1999
--- apache13/src/include/http_vhost.h	Wed Jan 27 13:58:19 1999
***************
*** 72,78 ****
  const char *ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s);
  
  /* handle NameVirtualHost directive */
! const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg);
  
  /* given an ip address only, give our best guess as to what vhost it is */
  void ap_update_vhost_given_ip(conn_rec *conn);
--- 72,78 ----
  const char *ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s);
  
  /* handle NameVirtualHost directive */
! 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 */
  void ap_update_vhost_given_ip(conn_rec *conn);
Index: apache13/src/include/httpd.h
diff -c apache13/src/include/httpd.h:1.1.1.4 apache13/src/include/httpd.h:1.6
*** apache13/src/include/httpd.h:1.1.1.4	Thu Mar 25 03:13:27 1999
--- apache13/src/include/httpd.h	Thu Mar 25 04:03:06 1999
***************
*** 798,805 ****
  
      /* Who is the client? */
  
!     struct sockaddr_in local_addr;	/* local address */
!     struct sockaddr_in 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,
--- 798,805 ----
  
      /* Who is the client? */
  
!     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,
***************
*** 834,841 ****
  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 */
      char *virthost;		/* The name given in <VirtualHost> */
  };
  
--- 834,841 ----
  typedef struct server_addr_rec server_addr_rec;
  struct server_addr_rec {
      server_addr_rec *next;
!     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 <VirtualHost> */
  };
  
***************
*** 899,905 ****
  /* 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 */
      int fd;
      int used;			/* Only used during restart */
  /* more stuff here, like which protocol is bound to the port */
--- 899,905 ----
  /* These are more like real hosts than virtual hosts */
  struct listen_rec {
      listen_rec *next;
!     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 */
***************
*** 1043,1049 ****
  #endif /* _OSD_POSIX */
  
  char *ap_get_local_host(pool *);
! unsigned long ap_get_virthost_addr(char *hostname, unsigned short *port);
  
  extern API_VAR_EXPORT time_t ap_restart_time;
  
--- 1043,1049 ----
  #endif /* _OSD_POSIX */
  
  char *ap_get_local_host(pool *);
! struct sockaddr *ap_get_virthost_addr(char *hostname, unsigned short *port);
  
  extern API_VAR_EXPORT time_t ap_restart_time;
  
Index: apache13/src/main/getaddrinfo.c
diff -c /dev/null apache13/src/main/getaddrinfo.c:1.1
*** /dev/null	Mon Mar 29 00:55:12 1999
--- apache13/src/main/getaddrinfo.c	Sun Jan 17 13:25:38 1999
***************
*** 0 ****
--- 1,119 ----
+ /*
+  * fake library for ssh
+  *
+  * 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 <stdlib.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include "gai.h"
+ #endif
+ 
+ static struct addrinfo *
+ malloc_ai(port, addr)
+ int port;
+ u_long addr;
+ {
+   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);
+     ai->ai_addr->sa_len = ai->ai_addrlen = sizeof(struct sockaddr_in);
+     ai->ai_addr->sa_family = ai->ai_family = AF_INET;
+     ((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)))
+       return 0;
+     else
+       return EAI_MEMORY;
+   if (!hostname)
+     if (*res = malloc_ai(port, htonl(0x7f000001)))
+       return 0;
+     else
+       return EAI_MEMORY;
+   if (inet_addr(hostname) != -1)
+     if (*res = malloc_ai(port, inet_addr(hostname)))
+       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)) {
+ 	if (prev)
+ 	  prev->ai_next = cur;
+ 	else
+ 	  *res = cur;
+ 	prev = cur;
+       } else {
+ 	if (*res)
+ 	  freeaddrinfo(*res);
+ 	return EAI_MEMORY;
+       }
+     return 0;
+   }
+   return EAI_NODATA;
+ }
Index: apache13/src/main/getnameinfo.c
diff -c /dev/null apache13/src/main/getnameinfo.c:1.1
*** /dev/null	Mon Mar 29 00:55:13 1999
--- apache13/src/main/getnameinfo.c	Sun Jan 17 13:25:38 1999
***************
*** 0 ****
--- 1,67 ----
+ /*
+  * fake library for ssh
+  *
+  * 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 <stdlib.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <string.h>
+ #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;
+ }
Index: apache13/src/main/http_config.c
diff -c apache13/src/main/http_config.c:1.1.1.4 apache13/src/main/http_config.c:1.6
*** apache13/src/main/http_config.c:1.1.1.4	Thu Mar 25 03:13:35 1999
--- apache13/src/main/http_config.c	Thu Mar 25 04:03:08 1999
***************
*** 1395,1401 ****
      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;
--- 1395,1415 ----
      ap_scoreboard_fname = DEFAULT_SCOREBOARD;
      ap_lock_fname = DEFAULT_LOCKFILE;
      ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
!     memset(&ap_bind_address, 0, sizeof(ap_bind_address));
!     ap_bind_address.ss_family = ap_default_family;
!     switch (ap_default_family) {
!     case AF_INET:
! 	ap_bind_address.ss_len = sizeof(struct sockaddr_in);
! 	break;
! #ifdef INET6
!     case AF_INET6:
! 	ap_bind_address.ss_len = sizeof(struct sockaddr_in6);
! 	break;
! #endif
!     default:
! 	fprintf(stderr, "unsupported address family %d\n", ap_default_family);
! 	exit(1);
!     }
      ap_listeners = NULL;
      ap_listenbacklog = DEFAULT_LISTENBACKLOG;
      ap_extended_status = 0;
***************
*** 1428,1434 ****
      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);
      s->addrs->host_port = 0;	/* matches any port */
      s->addrs->virthost = "";	/* must be non-NULL */
      s->names = s->wild_names = NULL;
--- 1442,1465 ----
      s->next = NULL;
      s->addrs = ap_pcalloc(p, sizeof(server_addr_rec));
      /* NOT virtual host; don't match any real network interface */
!     memset(&s->addrs->host_addr, 0, sizeof(s->addrs->host_addr));
!     s->addrs->host_addr.ss_family = ap_default_family;
!     switch (ap_default_family) {
!     case AF_INET:
! 	s->addrs->host_addr.ss_len = sizeof(struct sockaddr_in);
! 	break;
! #ifdef INET6
!     case AF_INET6:
! 	s->addrs->host_addr.ss_len = sizeof(struct sockaddr_in6);
! 	break;
! #endif
!     default:
! 	fprintf(stderr, "unsupported address family %d\n", ap_default_family);
! 	exit(1);
!     }
! #if 0
!     s->addrs->host_addr.su_port = 0;	/* matches any port */
! #endif
      s->addrs->host_port = 0;	/* matches any port */
      s->addrs->virthost = "";	/* must be non-NULL */
      s->names = s->wild_names = NULL;
***************
*** 1449,1457 ****
      }
      /* 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;
!     new->local_addr.sin_port = htons(s->port ? s->port : DEFAULT_HTTP_PORT);
      new->fd = -1;
      new->used = 0;
      new->next = NULL;
--- 1480,1498 ----
      }
      /* allocate a default listener */
      new = ap_pcalloc(p, sizeof(listen_rec));
!     new->local_addr = ap_bind_address;
!     switch (new->local_addr.ss_family) {
!     case AF_INET:
! 	((struct sockaddr_in *)&new->local_addr)->sin_port =
! 	    htons(s->port ? s->port : DEFAULT_HTTP_PORT);
! 	break;
! #ifdef INET6
!     case AF_INET6:
! 	((struct sockaddr_in6 *)&new->local_addr)->sin6_port =
! 	    htons(s->port ? s->port : DEFAULT_HTTP_PORT);
! 	break;
! #endif
!     }
      new->fd = -1;
      new->used = 0;
      new->next = NULL;
Index: apache13/src/main/http_core.c
diff -c apache13/src/main/http_core.c:1.1.1.4 apache13/src/main/http_core.c:1.12
*** apache13/src/main/http_core.c:1.1.1.4	Thu Mar 25 03:13:37 1999
--- apache13/src/main/http_core.c	Thu Mar 25 04:03:09 1999
***************
*** 541,547 ****
  /* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
  static ap_inline void do_double_reverse (conn_rec *conn)
  {
!     struct hostent *hptr;
  
      if (conn->double_reverse) {
  	/* already done */
--- 541,550 ----
  /* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
  static ap_inline void do_double_reverse (conn_rec *conn)
  {
!     struct addrinfo hints, *res, *res0;
!     struct sockaddr *sa;
!     struct sockaddr_in *sin;
!     struct sockaddr_in6 *sin6;
  
      if (conn->double_reverse) {
  	/* already done */
***************
*** 552,579 ****
  	conn->double_reverse = -1;
  	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;
  	    }
  	}
      }
      conn->double_reverse = -1;
  }
  
  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 */
  
      /* If we haven't checked the host name, and we want to */
      if (dir_config) {
--- 555,610 ----
  	conn->double_reverse = -1;
  	return;
      }
!     memset(&hints, 0, sizeof(hints));
!     hints.ai_family = PF_UNSPEC;
!     if (getaddrinfo(conn->remote_host, NULL, &hints, &res)) {
! 	conn->double_reverse = -1;
! 	return;
!     }
!     res0 = res;
!     while (res) {
! 	sa = (struct sockaddr *)res->ai_addr;
! 	if (sa->sa_len != conn->remote_addr.ss_len)
! 	    continue;
! 	if (sa->sa_family != conn->remote_addr.ss_family)
! 	    continue;
! 	switch (sa->sa_family) {
! 	case AF_INET:
! 	    sin = (struct sockaddr_in *)sa;
! 	    if (memcmp(&sin->sin_addr,
! 		    &((struct sockaddr_in *)&conn->remote_addr)->sin_addr,
! 		    sizeof(sin->sin_addr)) == 0) {
! 		conn->double_reverse = 1;
! 		freeaddrinfo(res0);
! 		return;
! 	    }
! 	    break;
! #ifdef INET6
! 	case AF_INET6:
! 	    sin6 = (struct sockaddr_in6 *)sa;
! 	    if (memcmp(&sin6->sin6_addr,
! 		    &((struct sockaddr_in6 *)&conn->remote_addr)->sin6_addr,
! 		    sizeof(sin6->sin6_addr)) == 0) {
  		conn->double_reverse = 1;
+ 		freeaddrinfo(res0);
  		return;
  	    }
+ 	    break;
+ #endif
+ 	default:
+ 	    break;
  	}
      }
      conn->double_reverse = -1;
+     freeaddrinfo(res0);
  }
  
  API_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
  					    int type)
  {
      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) {
***************
*** 595,604 ****
  	    || 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);
  	    ap_str_tolower(conn->remote_host);
  	   
  	    if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
--- 626,635 ----
  	    || hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
  	old_stat = ap_update_child_status(conn->child_num, SERVER_BUSY_DNS,
  					  (request_rec*)NULL);
! 	if (!getnameinfo((struct sockaddr *)&conn->remote_addr,
! 		conn->remote_addr.ss_len, 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) {
***************
*** 691,698 ****
      if (d->use_canonical_name & 1) {
  	return port;
      }
!     return r->hostname ? ntohs(r->connection->local_addr.sin_port)
! 		       : port;
  }
  
  API_EXPORT(char *) ap_construct_url(pool *p, const char *uri,
--- 722,730 ----
      if (d->use_canonical_name & 1) {
  	return port;
      }
!     return r->hostname
! 	? ntohs(((struct sockaddr_in *)&r->connection->local_addr)->sin_port)
! 	: port;
  }
  
  API_EXPORT(char *) ap_construct_url(pool *p, const char *uri,
***************
*** 709,715 ****
      }
      else {
          if (r->hostname) {
!             port = ntohs(r->connection->local_addr.sin_port);
  	}
          else if (r->server->port) {
              port = r->server->port;
--- 741,747 ----
      }
      else {
          if (r->hostname) {
!             port = ntohs(((struct sockaddr_in *)&r->connection->local_addr)->sin_port);
  	}
          else if (r->server->port) {
              port = r->server->port;
***************
*** 2332,2384 ****
  
  static const char *set_bind_address(cmd_parms *cmd, void *dummy, char *arg) 
  {
      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);
      return NULL;
  }
  
! static const char *set_listener(cmd_parms *cmd, void *dummy, char *ips)
  {
      listen_rec *new;
!     char *ports;
!     unsigned short port;
  
      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 :<port-number>";
  	}
! 	*(ports++) = '\0';
!     }
!     else {
! 	ports = ips;
      }
  
!     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);
!     }
!     port = atoi(ports);
!     if (!port) {
! 	return "Port must be numeric";
      }
!     new->local_addr.sin_port = htons(port);
      new->fd = -1;
      new->used = 0;
      new->next = ap_listeners;
--- 2364,2459 ----
  
  static const char *set_bind_address(cmd_parms *cmd, void *dummy, char *arg) 
  {
+     struct addrinfo hints, *res;
+     int error;
      const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
      if (err != NULL) {
          return err;
      }
+ 
+     if (strcmp(arg, "*") == 0)
+ 	arg = NULL;
+     memset(&hints, 0, sizeof(hints));
+     if (arg)
+ 	hints.ai_family = PF_UNSPEC;
+     else
+ 	hints.ai_family = ap_default_family;
+     hints.ai_flags = AI_PASSIVE;
+     error = getaddrinfo(arg, "0", &hints, &res);
+     if (error)
+ 	return "address resolution failed\n";
  
!     memcpy(&ap_bind_address, res->ai_addr, res->ai_addrlen);
!     freeaddrinfo(res);
      return NULL;
  }
  
! static const char *set_listener(cmd_parms *cmd, void *dummy, char *h, char *p)
  {
      listen_rec *new;
!     char *host, *port;
!     struct addrinfo hints, *res;
!     int error;
  
      const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
      if (err != NULL) {
          return err;
      }
  
!     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-number>";
! 	    }
! 	    *(port++) = '\0';
! 	    if (*h)
! 		host = h;
! 	} else {
! 	    host = NULL;
! 	    port = h;
  	}
!     } else {
! 	host = h;
! 	port = p;
      }
  
!     if (host && strcmp(host, "*") == 0)
! 	host = NULL;
! 
!     new = ap_pcalloc(cmd->pool, sizeof(listen_rec));
! 
!     memset(&hints, 0, sizeof(hints));
!     if (host)
! 	hints.ai_family = PF_UNSPEC;
!     else
! 	hints.ai_family = ap_default_family;
!     hints.ai_flags = AI_PASSIVE;
!     error = getaddrinfo(host, port, &hints, &res);
!     if (error || !res) {
! 	fprintf(stderr, "could not resolve ");
! 	if (host)
! 	    fprintf(stderr, "host \"%s\" ", host);
! 	if (port)
! 	    fprintf(stderr, "port \"%s\" ", port);
! 	fprintf(stderr, "--- %s\n", gai_strerror(error));
! 	exit(1);
!     }
!     if (res->ai_next) {
! 	if (host)
! 	    fprintf(stderr, "host \"%s\" ", host);
! 	if (port)
! 	    fprintf(stderr, "port \"%s\" ", port);
! 	fprintf(stderr, "resolved to multiple addresses, ambiguous.\n");
! 	exit(1);
      }
! 
!     memcpy(&new->local_addr, res->ai_addr, res->ai_addrlen);
! 
      new->fd = -1;
      new->used = 0;
      new->next = ap_listeners;
***************
*** 2832,2838 ****
     OR_ALL, TAKE12, "soft/hard limits for max number of processes per uid" },
  { "BindAddress", set_bind_address, NULL, RSRC_CONF, TAKE1,
    "'*', a numeric IP address, or the name of a host with a unique IP address"},
! { "Listen", set_listener, NULL, RSRC_CONF, TAKE1,
    "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"},
--- 2907,2913 ----
     OR_ALL, TAKE12, "soft/hard limits for max number of processes per uid" },
  { "BindAddress", set_bind_address, NULL, RSRC_CONF, TAKE1,
    "'*', a numeric IP address, or the name of a host with a unique IP address"},
! { "Listen", set_listener, NULL, RSRC_CONF, 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"},
***************
*** 2853,2859 ****
    "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,
    "A numeric IP address:port, or the name of a host" },
  #ifdef _OSD_POSIX
  { "BS2000Account", set_bs2000_account, NULL, RSRC_CONF, TAKE1,
--- 2928,2934 ----
    "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, TAKE12,
    "A numeric IP address:port, or the name of a host" },
  #ifdef _OSD_POSIX
  { "BS2000Account", set_bs2000_account, NULL, RSRC_CONF, TAKE1,
Index: apache13/src/main/http_main.c
diff -c apache13/src/main/http_main.c:1.1.1.4 apache13/src/main/http_main.c:1.10
*** apache13/src/main/http_main.c:1.1.1.4	Thu Mar 25 03:13:40 1999
--- apache13/src/main/http_main.c	Thu Mar 25 04:03:10 1999
***************
*** 239,245 ****
  char *ap_scoreboard_fname;
  char *ap_lock_fname;
  char *ap_server_argv0;
! struct in_addr ap_bind_address;
  int ap_daemons_to_start;
  int ap_daemons_min_free;
  int ap_daemons_max_free;
--- 239,246 ----
  char *ap_scoreboard_fname;
  char *ap_lock_fname;
  char *ap_server_argv0;
! int ap_default_family = AF_INET;
! struct sockaddr_storage ap_bind_address;
  int ap_daemons_to_start;
  int ap_daemons_min_free;
  int ap_daemons_max_free;
***************
*** 983,989 ****
      fprintf(stderr, "Usage: %s [-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]\n", pad);
      fprintf(stderr, "Options:\n");
  #ifdef SHARED_CORE
      fprintf(stderr, "  -R directory     : specify an alternate location for shared object files\n");
--- 984,994 ----
      fprintf(stderr, "Usage: %s [-d directory] [-f file]\n", bin);
  #endif
      fprintf(stderr, "       %s [-C \"directive\"] [-c \"directive\"]\n", pad);
!     fprintf(stderr, "       %s [-v] [-V] [-h] [-l] [-S] [-t]"
! #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");
***************
*** 1000,1005 ****
--- 1005,1014 ----
      fprintf(stderr, "  -L               : list available configuration directives\n");
      fprintf(stderr, "  -S               : show parsed settings (currently only vhost settings)\n");
      fprintf(stderr, "  -t               : run syntax test for configuration files only\n");
+ #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, "  -k shutdown      : tell running Apache to shutdown\n");
      fprintf(stderr, "  -k restart       : tell running Apache to do a graceful restart\n");
***************
*** 2950,2960 ****
  
  
  static conn_rec *new_connection(pool *p, server_rec *server, BUFF *inout,
! 			     const struct sockaddr_in *remaddr,
! 			     const struct sockaddr_in *saddr,
  			     int child_num)
  {
      conn_rec *conn = (conn_rec *) ap_pcalloc(p, sizeof(conn_rec));
  
      /* Got a connection structure, so initialize what fields we can
       * (the rest are zeroed out by pcalloc).
--- 2959,2970 ----
  
  
  static conn_rec *new_connection(pool *p, server_rec *server, BUFF *inout,
! 			     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];
  
      /* Got a connection structure, so initialize what fields we can
       * (the rest are zeroed out by pcalloc).
***************
*** 2963,2977 ****
      conn->child_num = child_num;
  
      conn->pool = p;
!     conn->local_addr = *saddr;
      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));
  
      return conn;
  }
--- 2973,2988 ----
      conn->child_num = child_num;
  
      conn->pool = p;
!     memcpy(&conn->local_addr, saddr, saddr->sa_len);
      conn->server = server; /* just a guess for now */
      ap_update_vhost_given_ip(conn);
      conn->base_server = conn->server;
      conn->client = inout;
  
!     memcpy(&conn->remote_addr, remaddr, remaddr->sa_len);
!     getnameinfo((struct sockaddr *)&conn->remote_addr, conn->remote_addr.ss_len,
! 	hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
!     conn->remote_ip = ap_pstrdup(conn->pool, hostnamebuf);
  
      return conn;
  }
***************
*** 3002,3022 ****
  #endif
  
  
! static int make_sock(pool *p, const struct sockaddr_in *server)
  {
      int s;
      int one = 1;
      char addr[512];
  
!     if (server->sin_addr.s_addr != htonl(INADDR_ANY))
! 	ap_snprintf(addr, sizeof(addr), "address %s port %d",
! 		inet_ntoa(server->sin_addr), ntohs(server->sin_port));
!     else
! 	ap_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
  
      /* 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) {
  	ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
  		    "make_sock: failed to get a socket for %s", addr);
  	ap_unblock_alarms();
--- 3013,3063 ----
  #endif
  
  
! static int make_sock(pool *p, const struct sockaddr *server)
  {
      int s;
      int one = 1;
      char addr[512];
+     char a0[512];
+     char p0[512];
+ #ifdef MPE
+     int privport;
  
!     privport = 0;
!     switch (server->sa_family) {
!     case AF_INET:
! 	if (ntohs(((struct sockaddr_in *)server)->sin_port) < 1024)
! 	    privport++;
! 	break;
! #ifdef INET6
!     case AF_INET6:
! 	if (ntohs(((struct sockaddr_in6 *)server)->sin6_port) < 1024)
! 	    privport++;
! 	break;
! #endif
!     }
! #endif
  
+     switch (server->sa_family) {
+ #ifdef INET6
+     case AF_INET6:
+ #endif
+     case AF_INET:
+ 	break;
+     default:
+ 	ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ 		    "make_sock: unsupported address family for %s", addr);
+ 	ap_unblock_alarms();
+ 	exit(1);
+     }
+ 
+     getnameinfo(server, server->sa_len,
+ 	    a0, sizeof(a0), p0, sizeof(p0), NI_NUMERICHOST | NI_NUMERICSERV);
+     ap_snprintf(addr, sizeof(addr), "address %s port %s", a0, p0);
+ 
      /* note that because we're about to slack we don't use psocket */
      ap_block_alarms();
!     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);
  	ap_unblock_alarms();
***************
*** 3108,3121 ****
  
  #ifdef MPE
  /* MPE requires CAP=PM and GETPRIVMODE to bind to ports less than 1024 */
!     if (ntohs(server->sin_port) < 1024)
  	GETPRIVMODE();
  #endif
!     if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) {
  	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)
  	    GETUSERMODE();
  #endif
  	close(s);
--- 3149,3162 ----
  
  #ifdef MPE
  /* MPE requires CAP=PM and GETPRIVMODE to bind to ports less than 1024 */
!     if (privport)
  	GETPRIVMODE();
  #endif
!     if (bind(s, server, server->sa_len) == -1) {
  	ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
  	    "make_sock: could not bind to %s", addr);
  #ifdef MPE
! 	if (privport)
  	    GETUSERMODE();
  #endif
  	close(s);
***************
*** 3123,3129 ****
  	exit(1);
      }
  #ifdef MPE
!     if (ntohs(server->sin_port) < 1024)
  	GETUSERMODE();
  #endif
  
--- 3164,3170 ----
  	exit(1);
      }
  #ifdef MPE
!     if (privport)
  	GETUSERMODE();
  #endif
  
***************
*** 3237,3243 ****
      for (;;) {
  	fd = find_listener(lr);
  	if (fd < 0) {
! 	    fd = make_sock(p, &lr->local_addr);
  	}
  	else {
  	    ap_note_cleanups_for_socket(p, fd);
--- 3278,3284 ----
      for (;;) {
  	fd = find_listener(lr);
  	if (fd < 0) {
! 	    fd = make_sock(p, (struct sockaddr *)&lr->local_addr);
  	}
  	else {
  	    ap_note_cleanups_for_socket(p, fd);
***************
*** 3511,3518 ****
  static void child_main(int child_num_arg)
  {
      NET_SIZE_T clen;
!     struct sockaddr sa_server;
!     struct sockaddr sa_client;
      listen_rec *lr;
  
      /* All of initialization is a critical section, we don't care if we're
--- 3552,3559 ----
  static void child_main(int child_num_arg)
  {
      NET_SIZE_T clen;
!     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
***************
*** 3674,3680 ****
  	    usr1_just_die = 0;
  	    for (;;) {
  		clen = sizeof(sa_client);
! 		csd = accept(sd, &sa_client, &clen);
  		if (csd >= 0 || errno != EINTR)
  		    break;
  		if (deferred_die) {
--- 3715,3721 ----
  	    usr1_just_die = 0;
  	    for (;;) {
  		clen = sizeof(sa_client);
! 		csd = accept(sd, (struct sockaddr *)&sa_client, &clen);
  		if (csd >= 0 || errno != EINTR)
  		    break;
  		if (deferred_die) {
***************
*** 3785,3791 ****
  	 */
  
  	clen = sizeof(sa_server);
! 	if (getsockname(csd, &sa_server, &clen) < 0) {
  	    ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "getsockname");
  	    continue;
  	}
--- 3826,3832 ----
  	 */
  
  	clen = sizeof(sa_server);
! 	if (getsockname(csd, (struct sockaddr *)&sa_server, &clen) < 0) {
  	    ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "getsockname");
  	    continue;
  	}
***************
*** 3828,3835 ****
  	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,
  				          my_child_num);
  
  	/*
--- 3869,3876 ----
  	ap_bpushfd(conn_io, csd, dupped_csd);
  
  	current_conn = new_connection(ptrans, server_conf, conn_io,
! 				          (struct sockaddr *)&sa_client,
! 				          (struct sockaddr *)&sa_server,
  				          my_child_num);
  
  	/*
***************
*** 4499,4505 ****
  
  #ifndef TPF
      while ((c = getopt(argc, argv,
! 				    "D:C:c:Xd:f:vVlLR:Sth"
  #ifdef DEBUG_SIGSTOP
  				    "Z:"
  #endif
--- 4540,4549 ----
  
  #ifndef TPF
      while ((c = getopt(argc, argv,
! 				    "D:C:c:Xd:f:vVhlL:St4"
! #ifdef INET6
! 				    "6"
! #endif
  #ifdef DEBUG_SIGSTOP
  				    "Z:"
  #endif
***************
*** 4562,4569 ****
  	case 't':
  	    configtestonly = 1;
  	    break;
! 	case 'h':
! 	    usage(argv[0]);
  	case '?':
  	    usage(argv[0]);
  	}
--- 4606,4619 ----
  	case 't':
  	    configtestonly = 1;
  	    break;
! 	case '4':
! 	    ap_default_family = AF_INET;
! 	    break;
! #ifdef INET6
! 	case '6':
! 	    ap_default_family = AF_INET6;
! 	    break;
! #endif
  	case '?':
  	    usage(argv[0]);
  	}
***************
*** 4593,4600 ****
      else {
  	conn_rec *conn;
  	request_rec *r;
- 	struct sockaddr sa_server, sa_client;
  	BUFF *cio;
  	NET_SIZE_T l;
  
  	ap_set_version();
--- 4643,4650 ----
      else {
  	conn_rec *conn;
  	request_rec *r;
  	BUFF *cio;
+ 	struct sockaddr_storage sa_server, sa_client;
  	NET_SIZE_T l;
  
  	ap_set_version();
***************
*** 4653,4677 ****
  #endif
  
  	l = sizeof(sa_client);
! 	if ((getpeername(sock_in, &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) {
  	    perror("getsockname");
  	    fprintf(stderr, "Error getting local address\n");
  	    exit(1);
  	}
! 	server_conf->port = ntohs(((struct sockaddr_in *) &sa_server)->sin_port);
  	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);
  
  	while ((r = ap_read_request(conn)) != NULL) {
  
--- 4703,4741 ----
  #endif
  
  	l = sizeof(sa_client);
! 	if ((getpeername(fileno(stdin), (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(fileno(stdin), (struct sockaddr *)&sa_server, &l) < 0) {
  	    perror("getsockname");
  	    fprintf(stderr, "Error getting local address\n");
  	    exit(1);
  	}
! 	switch (sa_server.ss_family) {
! 	case AF_INET:
! 	    server_conf->port =
! 		ntohs(((struct sockaddr_in *)&sa_server)->sin_port);
! 	    break;
! #ifdef INET6
! 	case AF_INET6:
! 	    server_conf->port =
! 		ntohs(((struct sockaddr_in6 *)&sa_server)->sin6_port);
! 	    break;
! #endif
! 	default:
! 	    fprintf(stderr, "unknown address family %d\n", sa_server.ss_family);
! 	    exit(1);
! 	}
  	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 *)&sa_client,
! 			          (struct sockaddr *)&sa_server, -1);
  
  	while ((r = ap_read_request(conn)) != NULL) {
  
***************
*** 6074,6080 ****
       * but only handle the -L option 
       */
      llp_dir = SHARED_CORE_DIR;
!     while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLR:SZ:th")) != -1) {
  	switch (c) {
  	case 'D':
  	case 'C':
--- 6138,6148 ----
       * but only handle the -L option 
       */
      llp_dir = SHARED_CORE_DIR;
!     while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVhlL:SZ:t4"
! #ifdef INET6
! 	"6"
! #endif
! 		)) != -1) {
  	switch (c) {
  	case 'D':
  	case 'C':
***************
*** 6089,6095 ****
  	case 'S':
  	case 'Z':
  	case 't':
! 	case 'h':
  	case '?':
  	    break;
  	case 'R':
--- 6157,6166 ----
  	case 'S':
  	case 'Z':
  	case 't':
! 	case '4':
! #ifdef INET6
! 	case '6':
! #endif
  	case '?':
  	    break;
  	case 'R':
Index: apache13/src/main/http_vhost.c
diff -c apache13/src/main/http_vhost.c:1.1.1.2 apache13/src/main/http_vhost.c:1.8
*** apache13/src/main/http_vhost.c:1.1.1.2	Tue Jan 12 13:34:35 1999
--- apache13/src/main/http_vhost.c	Wed Jan 27 13:58:22 1999
***************
*** 164,239 ****
   * *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)
  {
!     struct hostent *hep;
!     unsigned long my_addr;
      server_addr_rec *sar;
!     char *t;
!     int i, is_an_ip_addr;
  
      if (*w == 0)
  	return NULL;
  
!     t = strchr(w, ':');
!     if (t) {
! 	if (strcmp(t + 1, "*") == 0) {
! 	    port = 0;
! 	}
! 	else if ((i = atoi(t + 1))) {
! 	    port = i;
! 	}
! 	else {
! 	    return ":port must be numeric";
  	}
! 	*t = 0;
      }
  
!     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;
      }
!     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;
!     }
! 
!     hep = gethostbyname(w);
! 
!     if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
  	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
! 	    "Cannot resolve host name %s --- ignoring!", w);
  	if (t != NULL)
  	    *t = ':';
  	return NULL;
      }
  
!     for (i = 0; hep->h_addr_list[i]; ++i) {
  	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;
  	sar->virthost = ap_pstrdup(p, w);
      }
  
      if (t != NULL)
  	*t = ':';
      return NULL;
--- 164,281 ----
   * *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, char *pstr,
! 	server_addr_rec ***paddr, unsigned port)
  {
!     struct addrinfo hints, *res, *res0;
      server_addr_rec *sar;
!     char *t = NULL;
!     char *hoststr, *portstr;
!     char portpool[10];
!     int error;
  
      if (*w == 0)
  	return NULL;
  
!     portstr = portpool;
!     ap_snprintf(portpool, sizeof(portpool), "%u", port);
!     if (!pstr) {
! 	t = strrchr(w, ':');
! 	if (t) {
! 	    if (strcmp(t + 1, "*") == 0) {
! 		portstr = "0";
! 	    }
! 	    else {
! 		portstr = t + 1;
! 	    }
! 	    *t = 0;
  	}
!     } else {
! 	portstr = pstr;
      }
  
!     memset(&hints, 0, sizeof(hints));
!     hints.ai_family = PF_UNSPEC;
      if (strcmp(w, "*") == 0) {
! 	hoststr = NULL;
! 	hints.ai_flags = AI_PASSIVE;
      }
!     else if (strcasecmp(w, "_default4_") == 0) {
! 	hoststr = "255.255.255.255";
      }
!     else if (strcasecmp(w, "_default6_") == 0) {
! 	hoststr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
      }
!     else if (strcasecmp(w, "_default_") == 0) {
! 	switch (ap_default_family) {
! 	case AF_INET:
! 	    hoststr = "255.255.255.255";
! 	    break;
! #ifdef INET6
! 	case AF_INET6:
! 	    hoststr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
! 	    break;
! #endif
! 	default:
! 	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
! 		"Unsupported address family %d --- ignoring!",
! 		ap_default_family);
! 	    if (t != NULL)
! 		*t = ':';
! 	    return NULL;
! 	}
!     }
!     else {
! 	hoststr = w;
!     }
! 
!     error = getaddrinfo(hoststr, portstr, &hints, &res);
!     if (error || !res) {
! 	/*
! 	 * In case numeric IPv6 address is specified without port part,
! 	 * we must try again with default port.
! 	 * XXX ugly
! 	 */
! 	if (pstr == NULL && t != NULL) {
  	    *t = ':';
! 	    error = getaddrinfo(hoststr, portpool, &hints, &res);
! 	    if (!(error || !res)) {
! 		goto resolved;
! 	    }
! 	}
  	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
! 	    "Cannot resolve host name %s --- ignoring!", hoststr);
  	if (t != NULL)
  	    *t = ':';
  	return NULL;
      }
+ resolved:
+     res0 = res;
  
!     while (res) {
  	sar = ap_pcalloc(p, sizeof(server_addr_rec));
  	**paddr = sar;
  	*paddr = &sar->next;
! 	memcpy(&sar->host_addr, res->ai_addr, res->ai_addrlen);
! 	switch (sar->host_addr.ss_family) {
! 	case AF_INET:
! 	    sar->host_port =
! 		ntohs(((struct sockaddr_in *)&sar->host_addr)->sin_port);
! 		break;
! #ifdef INET6
! 	case AF_INET6:
! 	    sar->host_port =
! 		ntohs(((struct sockaddr_in6 *)&sar->host_addr)->sin6_port);
! 	    break;
! #endif
! 	default:
! 	    sar->host_port = 0;	/*XXX*/
! 	}
  	sar->virthost = ap_pstrdup(p, w);
+ 	res = res->ai_next;
      }
  
+     freeaddrinfo(res0);
      if (t != NULL)
  	*t = ':';
      return NULL;
***************
*** 249,255 ****
      /* start the list of addreses */
      addrs = &s->addrs;
      while (hostname[0]) {
! 	err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);
  	if (err) {
  	    *addrs = NULL;
  	    return err;
--- 291,298 ----
      /* start the list of addreses */
      addrs = &s->addrs;
      while (hostname[0]) {
! 	err = get_addresses(p, ap_getword_conf(p, &hostname), NULL,
! 		&addrs, s->port);
  	if (err) {
  	    *addrs = NULL;
  	    return err;
***************
*** 267,276 ****
  }
  
  
! const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg)
  {
      /* use whatever port the main server has at this point */
!     return get_addresses(cmd->pool, arg, &name_vhost_list_tail,
  			    cmd->server->port);
  }
  
--- 310,320 ----
  }
  
  
! 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, h, p, &name_vhost_list_tail,
  			    cmd->server->port);
  }
  
***************
*** 344,349 ****
--- 388,406 ----
      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_addr32[3]);
+ #endif
+     default:
+ 	return hash_inaddr(sa->sa_family);
+     }
+ }
  
  
  static ipaddr_chain *new_ipaddr_chain(pool *p,
***************
*** 372,393 ****
  }
  
  
! static ap_inline ipaddr_chain *find_ipaddr(struct in_addr *server_ip,
!     unsigned port)
  {
      unsigned bucket;
      ipaddr_chain *trav;
-     unsigned addr;
  
      /* scan the hash table for an exact match first */
!     addr = server_ip->s_addr;
!     bucket = hash_inaddr(addr);
      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;
  	}
      }
      return NULL;
--- 429,478 ----
  }
  
  
! static ap_inline ipaddr_chain *find_ipaddr(struct sockaddr *sa)
  {
      unsigned bucket;
      ipaddr_chain *trav;
  
      /* scan the hash table for an exact match first */
!     bucket = hash_addr(sa);
      for (trav = iphash_table[bucket]; trav; trav = trav->next) {
  	server_addr_rec *sar = trav->sar;
! 	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;
  	}
      }
      return NULL;
***************
*** 424,431 ****
  		ap_snprintf(buf, sizeof(buf), "%pA:*", &ic->sar->host_addr);
  	    }
  	    else {
! 		ap_snprintf(buf, sizeof(buf), "%pA:%u", &ic->sar->host_addr,
! 		    ic->sar->host_port);
  	    }
  	    if (ic->names == NULL) {
  		fprintf(f, "%-22s %s (%s:%u)\n", buf,
--- 509,515 ----
  		ap_snprintf(buf, sizeof(buf), "%pA:*", &ic->sar->host_addr);
  	    }
  	    else {
! 		ap_snprintf(buf, sizeof(buf), "%pI", &ic->sar->host_addr);
  	    }
  	    if (ic->names == NULL) {
  		fprintf(f, "%-22s %s (%s:%u)\n", buf,
***************
*** 496,502 ****
       * 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);
  	ipaddr_chain *new = new_ipaddr_chain(p, NULL, sar);
  
  	*iphash_table_tail[bucket] = new;
--- 580,586 ----
       * occured in the config file, we'll copy it in that order.
       */
      for (sar = name_vhost_list; sar; sar = sar->next) {
! 	unsigned bucket = hash_addr((struct sockaddr *)&sar->host_addr);
  	ipaddr_chain *new = new_ipaddr_chain(p, NULL, sar);
  
  	*iphash_table_tail[bucket] = new;
***************
*** 517,525 ****
  	has_default_vhost_addr = 0;
  	for (sar = s->addrs; sar; sar = sar->next) {
  	    ipaddr_chain *ic;
  
! 	    if (sar->host_addr.s_addr == DEFAULT_VHOST_ADDR
! 		|| sar->host_addr.s_addr == INADDR_ANY) {
  		/* add it to default bucket for each appropriate sar
  		 * since we need to do a port test
  		 */
--- 601,637 ----
  	has_default_vhost_addr = 0;
  	for (sar = s->addrs; sar; sar = sar->next) {
  	    ipaddr_chain *ic;
+ 	    int wildcard;
+ 
+ 	    wildcard = 0;
+ 	    switch (sar->host_addr.ss_family) {
+ 	    case AF_INET:
+ 	      {
+ 		struct sockaddr_in *sin;
+ 		sin = (struct sockaddr_in *)&sar->host_addr;
+ 		if (sin->sin_addr.s_addr == DEFAULT_VHOST_ADDR)
+ 		    wildcard++;
+ 		else if (sin->sin_addr.s_addr == INADDR_ANY)
+ 		    wildcard++;
+ 		break;
+ 	      }
+ #ifdef INET6
+ 	    case AF_INET6:
+ 	      {
+ 		struct sockaddr_in6 *sin6;
+ 		sin6 = (struct sockaddr_in6 *)&sar->host_addr;
+ 		if (sin6->sin6_addr.s6_addr32[0] == ~0
+ 		 && sin6->sin6_addr.s6_addr32[1] == ~0
+ 		 && sin6->sin6_addr.s6_addr32[2] == ~0
+ 		 && sin6->sin6_addr.s6_addr32[3] == ~0) {
+ 		    wildcard++;
+ 		}
+ 		break;
+ 	      }
+ #endif
+ 	    }
  
! 	    if (wildcard) {
  		/* add it to default bucket for each appropriate sar
  		 * since we need to do a port test
  		 */
***************
*** 538,544 ****
  	    }
  	    else {
  		/* see if it matches something we've already got */
! 		ic = find_ipaddr(&sar->host_addr, sar->host_port);
  
  		/* the first time we encounter a NameVirtualHost address
  		 * ic->server will be NULL, on subsequent encounters
--- 650,656 ----
  	    }
  	    else {
  		/* see if it matches something we've already got */
! 		ic = find_ipaddr((struct sockaddr *)&sar->host_addr);
  
  		/* the first time we encounter a NameVirtualHost address
  		 * ic->server will be NULL, on subsequent encounters
***************
*** 570,576 ****
  		    ic->server = s;
  		}
  		else {
! 		    unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
  
  		    ic = new_ipaddr_chain(p, s, sar);
  		    ic->next = *iphash_table_tail[bucket];
--- 682,689 ----
  		    ic->server = s;
  		}
  		else {
! 		    unsigned bucket =
! 			hash_addr((struct sockaddr *)&sar->host_addr);
  
  		    ic = new_ipaddr_chain(p, s, sar);
  		    ic->next = *iphash_table_tail[bucket];
***************
*** 597,615 ****
  	    }
  	    else {
  		struct hostent *h;
  
! 		if ((h = gethostbyaddr((char *) &(s->addrs->host_addr),
! 					sizeof(struct in_addr), AF_INET))) {
! 		    s->server_hostname = ap_pstrdup(p, (char *) h->h_name);
  		}
  		else {
  		    /* again, what can we do?  They didn't specify a
  		       ServerName, and their DNS isn't working. -djg */
  		    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));
  		    s->server_hostname =
  			ap_pstrdup(p, "bogus_host_without_reverse_dns");
  		}
--- 710,734 ----
  	    }
  	    else {
  		struct hostent *h;
+ 		char hostnamebuf[MAXHOSTNAMELEN];
  
! 		if (!getnameinfo((struct sockaddr *)&s->addrs->host_addr,
! 			s->addrs->host_addr.ss_len,
! 			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,
+ 			s->addrs->host_addr.ss_len,
+ 			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", hostnamebuf);
  		    s->server_hostname =
  			ap_pstrdup(p, "bogus_host_without_reverse_dns");
  		}
***************
*** 774,784 ****
       *   names we'll match have ports associated with them
       */
      const char *host = r->hostname;
!     unsigned port = ntohs(r->connection->local_addr.sin_port);
      server_rec *s;
      server_rec *last_s;
      name_chain *src;
  
      last_s = NULL;
  
      /* Recall that the name_chain is a list of server_addr_recs, some of
--- 893,917 ----
       *   names we'll match have ports associated with them
       */
      const char *host = r->hostname;
!     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
***************
*** 833,840 ****
      server_rec *s;
      server_rec *last_s;
      name_chain *src;
!     unsigned port = ntohs(r->connection->local_addr.sin_port);
  
      /*
       * This is in conjunction with the ServerPath code in http_core, so we
       * get the right host attached to a non- Host-sending request.
--- 966,988 ----
      server_rec *s;
      server_rec *last_s;
      name_chain *src;
!     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
       * get the right host attached to a non- Host-sending request.
***************
*** 891,900 ****
  void ap_update_vhost_given_ip(conn_rec *conn)
  {
      ipaddr_chain *trav;
!     unsigned port = ntohs(conn->local_addr.sin_port);
  
      /* scan the hash table for an exact match first */
!     trav = find_ipaddr(&conn->local_addr.sin_addr, port);
      if (trav) {
  	/* save the name_chain for later in case this is a name-vhost */
  	conn->vhost_lookup_data = trav->names;
--- 1039,1061 ----
  void ap_update_vhost_given_ip(conn_rec *conn)
  {
      ipaddr_chain *trav;
!     unsigned port;
! 
!     switch (conn->local_addr.ss_family) {
!     case AF_INET:
!     	port = ntohs(((struct sockaddr_in *)&conn->local_addr)->sin_port);
! 	break;
! #ifdef INET6
!     case AF_INET6:
!     	port = ntohs(((struct sockaddr_in6 *)&conn->local_addr)->sin6_port);
! 	break;
! #endif
!     default:
! 	port = 0;	/*XXX*/
!     }
  
      /* scan the hash table for an exact match first */
!     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;
Index: apache13/src/main/rfc1413.c
diff -c apache13/src/main/rfc1413.c:1.1.1.2 apache13/src/main/rfc1413.c:1.2
*** apache13/src/main/rfc1413.c:1.1.1.2	Tue Jan 12 13:34:38 1999
--- apache13/src/main/rfc1413.c	Sun Jan 17 13:23:07 1999
***************
*** 102,113 ****
  
  /* 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, 
  		       char user[RFC1413_USERLEN+1], server_rec *srv)
  {
!     struct sockaddr_in rmt_query_sin, our_query_sin;
!     unsigned int rmt_port, our_port;
      int i;
      char *cp;
      char buffer[RFC1413_MAXDATA + 1];
--- 102,114 ----
  
  /* bind_connect - bind both ends of a socket */
  /* Ambarish fix this. Very broken */
! 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_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];
***************
*** 122,134 ****
       * addresses from the query socket.
       */
  
!     our_query_sin = *our_sin;
!     our_query_sin.sin_port = htons(ANY_PORT);
!     rmt_query_sin = *rmt_sin;
!     rmt_query_sin.sin_port = htons(RFC1413_PORT);
  
      if (bind(sock, (struct sockaddr *) &our_query_sin,
! 	     sizeof(struct sockaddr_in)) < 0) {
  	ap_log_error(APLOG_MARK, APLOG_CRIT, srv,
  		    "bind: rfc1413: Error binding to local port");
  	return -1;
--- 123,164 ----
       * addresses from the query socket.
       */
  
!     memcpy(&our_query_sin, our_sin, our_sin->sa_len);
!     switch (our_sin->sa_family) {
!     case AF_INET:
! 	((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT);
! 	o_our_port = ntohs(((struct sockaddr_in *)our_sin)->sin_port);
! 	break;
! #ifdef INET6
!     case AF_INET6:
! 	((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT);
! 	o_our_port = ntohs(((struct sockaddr_in6 *)our_sin)->sin6_port);
! 	break;
! #endif
!     default:
! 	/* unsupported AF */
! 	return -1;
!     }
!     memcpy(&rmt_query_sin, rmt_sin, rmt_sin->sa_len);
!     switch (our_sin->sa_family) {
!     case AF_INET:
! 	((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:
! 	((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,
! 	     our_query_sin.ss_len) < 0) {
  	ap_log_error(APLOG_MARK, APLOG_CRIT, srv,
  		    "bind: rfc1413: Error binding to local port");
  	return -1;
***************
*** 139,150 ****
   * the service
   */
      if (connect(sock, (struct sockaddr *) &rmt_query_sin,
! 		sizeof(struct sockaddr_in)) < 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));
  
      /* send query to server. Handle short write. */
      i = 0;
--- 169,180 ----
   * the service
   */
      if (connect(sock, (struct sockaddr *) &rmt_query_sin,
! 		rmt_query_sin.ss_len) < 0)
  	            return -1;
  
  /* send the data */
!     buflen = ap_snprintf(buffer, sizeof(buffer), "%u,%u\r\n", o_rmt_port,
! 		o_our_port);
  
      /* send query to server. Handle short write. */
      i = 0;
***************
*** 184,192 ****
  
  /* RFC1413_USERLEN = 512 */
      if (sscanf(buffer, "%u , %u : USERID :%*[^:]:%512s", &rmt_port, &our_port,
! 	       user) != 3 || ntohs(rmt_sin->sin_port) != rmt_port
! 	|| ntohs(our_sin->sin_port) != our_port)
  	return -1;
  
      /*
       * Strip trailing carriage return. It is part of the
--- 214,222 ----
  
  /* RFC1413_USERLEN = 512 */
      if (sscanf(buffer, "%u , %u : USERID :%*[^:]:%512s", &rmt_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
***************
*** 227,234 ****
      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)
  	    result = user;
      }
      ap_set_callback_and_alarm(NULL, 0);
      ap_pclosesocket(conn->pool, sock);
--- 257,266 ----
      if (ap_setjmp(timebuf) == 0) {
  	ap_set_callback_and_alarm(ident_timeout, ap_rfc1413_timeout);
  
! 	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);
Index: apache13/src/main/util.c
diff -c apache13/src/main/util.c:1.1.1.4 apache13/src/main/util.c:1.9
*** apache13/src/main/util.c:1.1.1.4	Thu Mar 25 03:13:47 1999
--- apache13/src/main/util.c	Thu Mar 25 04:03:12 1999
***************
*** 1827,1868 ****
   * Parses a host of the form <address>[:port]
   * :port is permitted if 'port' is not NULL
   */
! unsigned long ap_get_virthost_addr(char *w, unsigned short *ports)
  {
!     struct hostent *hep;
!     unsigned long my_addr;
      char *p;
  
!     p = strchr(w, ':');
      if (ports != NULL) {
- 	*ports = 0;
  	if (p != NULL && strcmp(p + 1, "*") != 0)
! 	    *ports = atoi(p + 1);
      }
  
      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;
!     }
  
!     hep = gethostbyname(w);
  
!     if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
! 	fprintf(stderr, "Cannot resolve host name %s --- exiting!\n", w);
  	exit(1);
      }
  
!     if (hep->h_addr_list[1]) {
  	fprintf(stderr, "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");
--- 1827,1868 ----
   * Parses a host of the form <address>[:port]
   * :port is permitted if 'port' is not NULL
   */
! struct sockaddr *ap_get_virthost_addr(char *w, unsigned short *ports)
  {
!     static struct sockaddr_storage ss;
!     struct addrinfo hints, *res;
      char *p;
+     char *host;
+     char *port;
+     int error;
  
!     memset(&hints, 0, sizeof(hints));
!     hints.ai_family = AF_UNSPEC;
! 
!     port = "0";
!     p = strrchr(w, ':');
      if (ports != NULL) {
  	if (p != NULL && strcmp(p + 1, "*") != 0)
! 	    port = p + 1;
      }
  
      if (p != NULL)
  	*p = '\0';
      if (strcmp(w, "*") == 0) {
! 	host = NULL;
! 	hints.ai_flags = AI_PASSIVE;
! 	hints.ai_family = ap_default_family;
!     } else
! 	host = w;
  
!     error = getaddrinfo(host, port, &hints, &res);
  
!     if (error || !res) {
! 	fprintf(stderr, "%s: %s --- exiting!\n", w, gai_strerror(error));
  	exit(1);
      }
  
!     if (res->ai_next) {
  	fprintf(stderr, "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");
***************
*** 1872,1878 ****
      if (p != NULL)
  	*p = ':';
  
!     return ((struct in_addr *) (hep->h_addr))->s_addr;
  }
  
  
--- 1872,1892 ----
      if (p != NULL)
  	*p = ':';
  
!     switch (res->ai_addr->sa_family) {
!     case AF_INET:
! 	*ports = ntohs(((struct sockaddr_in *)res->ai_addr)->sin_port);
! 	break;
! #ifdef INET6
!     case AF_INET6:
! 	*ports = ntohs(((struct sockaddr_in6 *)res->ai_addr)->sin6_port);
! 	break;
! #endif
!     default:
! 	*ports = 0;	/*XXX*/
!     }
!     memcpy(&ss, res->ai_addr, res->ai_addrlen);
!     freeaddrinfo(res);
!     return (struct sockaddr *)&ss;
  }
  
  
***************
*** 1897,1918 ****
  #define MAXHOSTNAMELEN 256
  #endif
      char str[MAXHOSTNAMELEN + 1];
!     char *server_hostname;
!     struct hostent *p;
  
      if (gethostname(str, sizeof(str) - 1) != 0) {
  	perror("Unable to gethostname");
  	exit(1);
      }
      str[MAXHOSTNAMELEN] = '\0';
!     if ((!(p = gethostbyname(str))) || (!(server_hostname = find_fqdn(a, p)))) {
! 	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);
      }
  
!     return server_hostname;
  }
  
  /* aaaack but it's fast and const should make it shared text page. */
--- 1911,1936 ----
  #define MAXHOSTNAMELEN 256
  #endif
      char str[MAXHOSTNAMELEN + 1];
!     struct addrinfo hints, *res;
!     int error;
  
      if (gethostname(str, sizeof(str) - 1) != 0) {
  	perror("Unable to gethostname");
  	exit(1);
      }
      str[MAXHOSTNAMELEN] = '\0';
!     memset(&hints, 0, sizeof(hints));
!     hints.ai_family = PF_UNSPEC;
!     hints.ai_flags = AI_CANONNAME;
!     error = getaddrinfo(str, NULL, &hints, &res);
!     if (error || !res || !res->ai_canonname) {
!   	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);
      }
  
!     return res->ai_canonname;
  }
  
  /* aaaack but it's fast and const should make it shared text page. */
***************
*** 2183,2185 ****
--- 2201,2211 ----
      *outchr = '\0';
      return outstring;
  }
+ 
+ #ifdef NEED_GETADDRINFO
+ #include "getaddrinfo.c"
+ #endif
+ 
+ #ifdef NEED_GETNAMEINFO
+ #include "getnameinfo.c"
+ #endif
Index: apache13/src/main/util_script.c
diff -c apache13/src/main/util_script.c:1.1.1.4 apache13/src/main/util_script.c:1.6
*** apache13/src/main/util_script.c:1.1.1.4	Thu Mar 25 03:13:51 1999
--- apache13/src/main/util_script.c	Thu Mar 25 04:03:13 1999
***************
*** 276,283 ****
      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)));
  
      if (c->user) {
  	ap_table_addn(e, "REMOTE_USER", c->user);
--- 276,295 ----
      ap_table_addn(e, "SERVER_ADMIN", s->server_admin);	/* Apache */
      ap_table_addn(e, "SCRIPT_FILENAME", r->filename);	/* Apache */
  
!     switch (c->remote_addr.ss_family) {
!     case AF_INET:
! 	ap_table_addn(e, "REMOTE_PORT",
! 		  ap_psprintf(r->pool, "%d",
! 		      ntohs(((struct sockaddr_in *)&c->remote_addr)->sin_port)));
! 	break;
! #ifdef INET6
!     case AF_INET6:
! 	ap_table_addn(e, "REMOTE_PORT",
! 		  ap_psprintf(r->pool, "%d",
! 		      ntohs(((struct sockaddr_in6 *)&c->remote_addr)->sin6_port)));
! #endif
! 	break;
!     }
  
      if (c->user) {
  	ap_table_addn(e, "REMOTE_USER", c->user);
Index: apache13/src/modules/proxy/mod_proxy.h
diff -c apache13/src/modules/proxy/mod_proxy.h:1.1.1.3 apache13/src/modules/proxy/mod_proxy.h:1.4
*** apache13/src/modules/proxy/mod_proxy.h:1.1.1.3	Thu Mar 25 03:14:28 1999
--- apache13/src/modules/proxy/mod_proxy.h	Thu Mar 25 04:03:15 1999
***************
*** 307,313 ****
  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_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);
--- 307,313 ----
  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 *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);
Index: apache13/src/modules/proxy/proxy_ftp.c
diff -c apache13/src/modules/proxy/proxy_ftp.c:1.1.1.3 apache13/src/modules/proxy/proxy_ftp.c:1.5
*** apache13/src/modules/proxy/proxy_ftp.c:1.1.1.3	Thu Mar 25 03:14:32 1999
--- apache13/src/modules/proxy/proxy_ftp.c	Thu Mar 25 04:03:16 1999
***************
*** 448,455 ****
      const char *err;
      int port, i, j, len, sock, dsock, rc, nocache = 0;
      int csd = 0;
!     struct sockaddr_in server;
!     struct hostent server_hp;
      struct in_addr destaddr;
      table *resp_hdrs;
      BUFF *f;
--- 448,457 ----
      const char *err;
      int port, i, j, len, sock, dsock, rc, nocache = 0;
      int csd = 0;
!     struct sockaddr_storage server;
!     struct addrinfo hints, *res, *res0;
!     char portbuf[10];
!     int error;
      struct in_addr destaddr;
      table *resp_hdrs;
      BUFF *f;
***************
*** 470,480 ****
      unsigned int presult, h0, h1, h2, h3, p0, p1;
      unsigned int paddr;
      unsigned short pport;
!     struct sockaddr_in data_addr;
      int pasvmode = 0;
      char pasv[64];
      char *pstr;
  
  /* stuff for responses */
      char resp[MAX_STRING_LEN];
      char *size = NULL;
--- 472,489 ----
      unsigned int presult, h0, h1, h2, h3, p0, p1;
      unsigned int paddr;
      unsigned short pport;
!     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;
***************
*** 542,602 ****
      parms = strchr(path, ';');
      if (parms != NULL)
  	*(parms++) = '\0';
- 
-     memset(&server, 0, sizeof(struct sockaddr_in));
-     server.sin_family = AF_INET;
-     server.sin_port = htons(port);
-     err = ap_proxy_host2addr(host, &server_hp);
-     if (err != NULL)
- 	return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
  
!     sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
!     if (sock == -1) {
! 	ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
! 		     "proxy: error creating socket");
! 	return HTTP_INTERNAL_SERVER_ERROR;
!     }
! 
!     if (conf->recv_buffer_size > 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 (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;
  #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)
  	    break;
! 	j++;
      }
! #endif
      if (i == -1) {
  	ap_pclosesocket(p, sock);
  	return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
--- 551,615 ----
      parms = strchr(path, ';');
      if (parms != NULL)
  	*(parms++) = '\0';
  
!     memset(&hints, 0, sizeof(hints));
!     hints.ai_family = AF_UNSPEC;
!     sprintf(portbuf, "%d", port);
!     error = getaddrinfo(host, portbuf, &hints, &res);
!     if (error) {
! 	return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
! 		    gai_strerror(error));
!     }
! 
!     res0 = res;
!     while (res) {
! 	sock = ap_psocket(p, res->ai_family, SOCK_STREAM, IPPROTO_TCP);
! 	if (sock == -1) {
! 	    if (res->ai_next) {
! 		res = res->ai_next;
! 		continue;
! 	    }
  	    ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
! 			 "proxy: error creating socket");
! 	    freeaddrinfo(res0);
! 	    return HTTP_INTERNAL_SERVER_ERROR;
! 	}
! 
! 	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 (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &one,
! 		       sizeof(one)) == -1) {
! 	    if (res->ai_next) {
! 		ap_pclosesocket(p, sock);
! 		res = res->ai_next;
! 		continue;
! 	    }
  #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);
! 	    freeaddrinfo(res0);
! 	    return HTTP_INTERNAL_SERVER_ERROR;
  #endif /*_OSD_POSIX*/
  	}
! 
! 	i = ap_proxy_doconnect(sock, res->ai_addr, r);
! 	if (i == 0) {
! 	    memcpy(&server, res->ai_addr, res->ai_addrlen);
  	    break;
! 	}
! 
! 	ap_pclosesocket(p, sock);
! 	res = res->ai_next;
      }
!     freeaddrinfo(res0);
! 
      if (i == -1) {
  	ap_pclosesocket(p, sock);
  	return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
***************
*** 800,806 ****
      }
  
  /* try to set up PASV data connection first */
!     dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
      if (dsock == -1) {
  	ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  		     "proxy: error creating PASV socket");
--- 813,819 ----
      }
  
  /* try to set up PASV data connection first */
!     dsock = ap_psocket(p, server.ss_family, SOCK_STREAM, IPPROTO_TCP);
      if (dsock == -1) {
  	ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  		     "proxy: error creating PASV socket");
***************
*** 817,827 ****
  	}
      }
  
!     ap_bputs("PASV" CRLF, f);
      ap_bflush(f);
!     Explain0("FTP: PASV command issued");
  /* possible results: 227, 421, 500, 501, 502, 530 */
      /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */
      /* 421 Service not available, closing control connection. */
      /* 500 Syntax error, command unrecognized. */
      /* 501 Syntax error in parameters or arguments. */
--- 830,850 ----
  	}
      }
  
! lpsvagain:
!     if (server.ss_family == AF_INET)
! 	cmd = "PASV";
!     else if (lpsvmode)
! 	cmd = "LPSV";
!     else
! 	cmd = "EPSV";
!     ap_bputs(cmd, f);
!     ap_bputs(CRLF, f);
      ap_bflush(f);
!     Explain0("FTP: passive command issued");
  /* possible results: 227, 421, 500, 501, 502, 530 */
      /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */
+     /* 228 Entering Long Passive Mode (...). */
+     /* 229 Entering Extended Passive Mode (...). */
      /* 421 Service not available, closing control connection. */
      /* 500 Syntax error, command unrecognized. */
      /* 501 Syntax error in parameters or arguments. */
***************
*** 830,836 ****
      i = ap_bgets(pasv, sizeof(pasv), f);
      if (i == -1) {
  	ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
! 		     "PASV: control connection is toast");
  	ap_pclosesocket(p, dsock);
  	ap_bclose(f);
  	ap_kill_timeout(r);
--- 853,859 ----
      i = ap_bgets(pasv, sizeof(pasv), f);
      if (i == -1) {
  	ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
! 		     "%s: control connection is toast", cmd);
  	ap_pclosesocket(p, dsock);
  	ap_bclose(f);
  	ap_kill_timeout(r);
***************
*** 862,871 ****
  	    pport = (p1 << 8) + p0;
  	    Explain5("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);
  
  	    if (i == -1) {
  		ap_kill_timeout(r);
--- 885,921 ----
  	    pport = (p1 << 8) + p0;
  	    Explain5("FTP: contacting host %d.%d.%d.%d:%d",
  		     h3, h2, h1, h0, pport);
! 	    sin = (struct sockaddr_in *)&data_addr;
! 	    sin->sin_family = AF_INET;
! 	    sin->sin_len = sizeof(*sin);
! 	    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) {
! 		ap_kill_timeout(r);
! 		return ap_proxyerror(r, HTTP_BAD_GATEWAY,
! 				     ap_pstrcat(r->pool,
! 						"Could not connect to remote machine: ",
! 						strerror(errno), NULL));
! 	    } else {
! 		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;
! 	    sin6->sin6_len = sizeof(*sin6);
! 	    for (i = 0; i < 16; i++)
! 		sin6->sin6_addr.s6_addr8[i] = ho[i] & 0xff;
! 	    sin6->sin6_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff));
! 	    i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r);
  
  	    if (i == -1) {
  		ap_kill_timeout(r);
***************
*** 873,889 ****
  				     ap_pstrcat(r->pool,
  						"Could not connect to remote machine: ",
  						strerror(errno), NULL));
  	    }
! 	    else {
  		pasvmode = 1;
  	    }
  	}
  	else
  	    ap_pclosesocket(p, dsock);	/* and try the regular way */
      }
  
      if (!pasvmode) {		/* set up data connection */
! 	clen = sizeof(struct sockaddr_in);
  	if (getsockname(sock, (struct sockaddr *) &server, &clen) < 0) {
  	    ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  			 "proxy: error getting socket address");
--- 923,967 ----
  				     ap_pstrcat(r->pool,
  						"Could not connect to remote machine: ",
  						strerror(errno), NULL));
+ 	    } else {
+ 		pasvmode = 1;
  	    }
! 	} else if (presult == 229 && pstr != NULL
! 		&& pstr[0] == pstr[1] && pstr[0] == pstr[2]
! 		&& pstr[0] == pstr[strlen(pstr) - 1]) {
! 	    /* expect "|||port|" */
! 	    memcpy(&data_addr, &server, server.ss_len);
! 	    switch (data_addr.ss_family) {
! 	    case AF_INET:
! 		sin = (struct sockaddr_in *)&data_addr;
! 		sin->sin_port = htons(atoi(pstr + 3));
! 		break;
! 	    case AF_INET6:
! 		sin6 = (struct sockaddr_in6 *)&data_addr;
! 		sin6->sin6_port = htons(atoi(pstr + 3));
! 		break;
! 	    }
! 	    i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r);
! 
! 	    if (i == -1) {
! 		ap_kill_timeout(r);
! 		return ap_proxyerror(r, HTTP_BAD_GATEWAY,
! 				     ap_pstrcat(r->pool,
! 						"Could not connect to remote machine: ",
! 						strerror(errno), NULL));
! 	    } else {
  		pasvmode = 1;
  	    }
+ 	} else if (!lpsvmode && strcmp(cmd, "EPSV") == 0) {
+ 	    lpsvmode = 1;
+ 	    goto lpsvagain;
  	}
  	else
  	    ap_pclosesocket(p, dsock);	/* and try the regular way */
      }
  
      if (!pasvmode) {		/* set up data connection */
! 	clen = sizeof(server);
  	if (getsockname(sock, (struct sockaddr *) &server, &clen) < 0) {
  	    ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  			 "proxy: error getting socket address");
***************
*** 892,898 ****
  	    return HTTP_INTERNAL_SERVER_ERROR;
  	}
  
! 	dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
  	if (dsock == -1) {
  	    ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  			 "proxy: error creating socket");
--- 970,976 ----
  	    return HTTP_INTERNAL_SERVER_ERROR;
  	}
  
! 	dsock = ap_psocket(p, server.ss_family, SOCK_STREAM, IPPROTO_TCP);
  	if (dsock == -1) {
  	    ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  			 "proxy: error creating socket");
***************
*** 913,925 ****
  #endif /*_OSD_POSIX*/
  	}
  
! 	if (bind(dsock, (struct sockaddr *) &server,
! 		 sizeof(struct sockaddr_in)) == -1) {
! 	    char buff[22];
  
! 	    ap_snprintf(buff, sizeof(buff), "%s:%d", inet_ntoa(server.sin_addr), server.sin_port);
  	    ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
! 			 "proxy: error binding to ftp data socket %s", buff);
  	    ap_bclose(f);
  	    ap_pclosesocket(p, dsock);
  	    return HTTP_INTERNAL_SERVER_ERROR;
--- 991,1006 ----
  #endif /*_OSD_POSIX*/
  	}
  
! 	if (bind(dsock, (struct sockaddr *) &server, server.ss_len) == -1) {
! 	    char hostnamebuf[MAXHOSTNAMELEN], portnamebuf[MAXHOSTNAMELEN];
  
! 	    getnameinfo((struct sockaddr *)&server, server.ss_len,
! 		hostnamebuf, sizeof(hostnamebuf),
! 		portnamebuf, sizeof(portnamebuf),
! 		NI_NUMERICHOST | NI_NUMERICSERV);
  	    ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
! 			 "proxy: error binding to ftp data socket %s:%s",
! 			 hostnamebuf, portnamebuf);
  	    ap_bclose(f);
  	    ap_pclosesocket(p, dsock);
  	    return HTTP_INTERNAL_SERVER_ERROR;
***************
*** 1158,1164 ****
  
      if (!pasvmode) {		/* wait for connection */
  	ap_hard_timeout("proxy ftp data connect", r);
! 	clen = sizeof(struct sockaddr_in);
  	do
  	    csd = accept(dsock, (struct sockaddr *) &server, &clen);
  	while (csd == -1 && errno == EINTR);
--- 1239,1245 ----
  
      if (!pasvmode) {		/* wait for connection */
  	ap_hard_timeout("proxy ftp data connect", r);
! 	clen = sizeof(server);
  	do
  	    csd = accept(dsock, (struct sockaddr *) &server, &clen);
  	while (csd == -1 && errno == EINTR);
Index: apache13/src/modules/proxy/proxy_http.c
diff -c apache13/src/modules/proxy/proxy_http.c:1.1.1.3 apache13/src/modules/proxy/proxy_http.c:1.6
*** apache13/src/modules/proxy/proxy_http.c:1.1.1.3	Thu Mar 25 03:14:34 1999
--- apache13/src/modules/proxy/proxy_http.c	Thu Mar 25 04:03:17 1999
***************
*** 175,193 ****
      array_header *reqhdrs_arr;
      table *resp_hdrs;
      table_entry *reqhdrs;
-     struct sockaddr_in server;
-     struct in_addr destaddr;
-     struct hostent server_hp;
      BUFF *f;
      char buffer[HUGE_STRING_LEN];
      char portstr[32];
      pool *p = r->pool;
      const long int zero = 0L;
-     int destport = 0;
      char *destportstr = NULL;
      const char *urlptr = NULL;
      const char *datestr;
      struct tbl_do_args tdo;
  
      void *sconf = r->server->module_config;
      proxy_server_conf *conf =
--- 175,191 ----
      array_header *reqhdrs_arr;
      table *resp_hdrs;
      table_entry *reqhdrs;
      BUFF *f;
      char buffer[HUGE_STRING_LEN];
      char portstr[32];
      pool *p = r->pool;
      const long int zero = 0L;
      char *destportstr = NULL;
      const char *urlptr = NULL;
      const char *datestr;
      struct tbl_do_args tdo;
+     struct addrinfo hints, *res, *tres;
+     int error;
  
      void *sconf = r->server->module_config;
      proxy_server_conf *conf =
***************
*** 196,211 ****
      struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts;
      int nocache = 0;
  
-     memset(&server, '\0', sizeof(server));
-     server.sin_family = AF_INET;
- 
  /* We break the URL into host, port, path-search */
  
      urlptr = strstr(url, "://");
      if (urlptr == NULL)
  	return HTTP_BAD_REQUEST;
      urlptr += 3;
!     destport = DEFAULT_HTTP_PORT;
      strp = strchr(urlptr, '/');
      if (strp == NULL) {
  	desthost = ap_pstrdup(p, urlptr);
--- 194,207 ----
      struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts;
      int nocache = 0;
  
  /* We break the URL into host, port, path-search */
  
      urlptr = strstr(url, "://");
      if (urlptr == NULL)
  	return HTTP_BAD_REQUEST;
      urlptr += 3;
!     ap_snprintf(portstr, sizeof(portstr), "%d", DEFAULT_HTTP_PORT);
!     destportstr = portstr;
      strp = strchr(urlptr, '/');
      if (strp == NULL) {
  	desthost = ap_pstrdup(p, urlptr);
***************
*** 219,271 ****
  	desthost = q;
      }
  
!     strp2 = strchr(desthost, ':');
      if (strp2 != NULL) {
  	*(strp2++) = '\0';
  	if (ap_isdigit(*strp2)) {
- 	    destport = atoi(strp2);
  	    destportstr = strp2;
  	}
      }
  
  /* check if ProxyBlock directive on this host */
!     destaddr.s_addr = ap_inet_addr(desthost);
!     for (i = 0; i < conf->noproxies->nelts; i++) {
! 	if ((npent[i].name != NULL && strstr(desthost, npent[i].name) != NULL)
! 	    || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
  	    return ap_proxyerror(r, HTTP_FORBIDDEN,
  				 "Connect to remote machine blocked");
!     }
! 
!     if (proxyhost != NULL) {
! 	server.sin_port = htons(proxyport);
! 	err = ap_proxy_host2addr(proxyhost, &server_hp);
! 	if (err != NULL)
! 	    return DECLINED;	/* try another */
!     }
!     else {
! 	server.sin_port = htons(destport);
! 	err = ap_proxy_host2addr(desthost, &server_hp);
! 	if (err != NULL)
! 	    return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
      }
  
!     sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
!     if (sock == -1) {
! 	ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
! 		    "proxy: error creating socket");
! 	return HTTP_INTERNAL_SERVER_ERROR;
      }
  
!     if (conf->recv_buffer_size) {
! 	if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
! 		       (const char *) &conf->recv_buffer_size, sizeof(int))
! 	    == -1) {
  	    ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
! 			 "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
  	}
      }
  
  #ifdef SINIX_D_RESOLVER_BUG
      {
  	struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list;
--- 215,342 ----
  	desthost = q;
      }
  
!     strp2 = strrchr(desthost, ':');
      if (strp2 != NULL) {
  	*(strp2++) = '\0';
  	if (ap_isdigit(*strp2)) {
  	    destportstr = strp2;
  	}
      }
  
+     /*
+      * numeric host in IPv6 URL
+      * anyway, it won't be accepted by upper-layers...
+      */
+     if (desthost[0] == '[' && desthost[strlen(desthost) - 1] == ']') {
+ 	desthost[strlen(desthost) - 1] == '\0';
+ 	desthost++;
+     }
+ 
+     memset(&hints, 0, sizeof(hints));
+     hints.ai_family = PF_UNSPEC;
+     hints.ai_socktype = SOCK_STREAM;
+     hints.ai_protocol = IPPROTO_TCP;
+     res = NULL;
+     error = getaddrinfo(desthost, destportstr, &hints, &res);
+     if (error || !res) {
+ 	if (res)
+ 	    freeaddrinfo(res);
+ 	return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
+ 		    gai_strerror(error));	/* give up */
+     }
+ 
  /* check if ProxyBlock directive on this host */
!     tres = res;
!     while (tres) {
! 	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 (tres->ai_addr->sa_family) {
! 	    case AF_INET:
! 		sin = (struct sockaddr_in *)tres->ai_addr;
! 		if (sin->sin_addr.s_addr == npent[i].addr.s_addr)
! 		    fail++;
! 		break;
! 	    }
! 	}
! 	if (fail) {
! 	    freeaddrinfo(res);
  	    return ap_proxyerror(r, HTTP_FORBIDDEN,
  				 "Connect to remote machine blocked");
! 	}
! 	tres = tres->ai_next;
      }
  
!     if (proxyhost) {
! 	freeaddrinfo(res);
! 	memset(&hints, 0, sizeof(hints));
! 	hints.ai_family = PF_UNSPEC;
! 	hints.ai_socktype = SOCK_STREAM;
! 	hints.ai_protocol = IPPROTO_TCP;
! 	res = NULL;
! 	if (proxyhost) {
! 	    char t[10];
! 	    ap_snprintf(t, sizeof(t), "%d", proxyport);
! 	    error = getaddrinfo(proxyhost, t, &hints, &res);
! 	} else
! 	    error = getaddrinfo(desthost, destportstr, &hints, &res);
! 	if (error || !res) {
! 	    if (res)
! 		freeaddrinfo(res);
! 	    if (proxyhost)
! 		return DECLINED;	/* try another */
! 	    else {
! 		return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
! 		    gai_strerror(error));
! 	    }
! 	}
      }
  
!     while (res) {
! 	sock = ap_psocket(p, res->ai_family, res->ai_socktype, res->ai_protocol);
! 	if (sock == -1) {
  	    ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
! 			"proxy: error creating socket");
! 	    res = res->ai_next;	/*try next one*/
! 	    continue;
  	}
+ 
+ 	if (conf->recv_buffer_size) {
+ 	    if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+ 			   (const char *) &conf->recv_buffer_size, sizeof(int))
+ 		== -1) {
+ 		ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ 			     "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
+ 	    }
+ 	}
+ 
+ 	i = ap_proxy_doconnect(sock, (struct sockaddr *)res->ai_addr, r);
+ 	if (i == 0)
+ 	    break;
+ 
+ 	close(sock);
+ 	res = res->ai_next;	/*try next one*/
+     }
+ 
+     if (i == -1 || !res) {
+ 	if (proxyhost != NULL)
+ 	    return DECLINED;	/* try again another way */
+ 	else
+ 	    return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
+ 				"Could not connect to remote machine: ",
+ 				strerror(errno), NULL));
      }
  
+ #if 0
  #ifdef SINIX_D_RESOLVER_BUG
      {
  	struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list;
***************
*** 288,293 ****
--- 359,365 ----
  	j++;
      }
  #endif
+ #endif
      if (i == -1) {
  	if (proxyhost != NULL)
  	    return DECLINED;	/* try again another way */
***************
*** 305,311 ****
      ap_hard_timeout("proxy send", r);
      ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.0" CRLF,
  	   NULL);
!     if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)
  	ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
      else
  	ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
--- 377,383 ----
      ap_hard_timeout("proxy send", r);
      ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.0" CRLF,
  	   NULL);
!     if (destportstr != NULL && atoi(destportstr) != DEFAULT_HTTP_PORT)
  	ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
      else
  	ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
***************
*** 462,472 ****
  	ap_table_set(resp_hdrs, "URI", proxy_location_reverse_map(r, datestr));
  
  /* check if NoCache directive on this host */
      for (i = 0; i < conf->nocaches->nelts; i++) {
! 	if ((ncent[i].name != NULL && strstr(desthost, ncent[i].name) != NULL)
! 	    || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*')
! 	    nocache = 1;
      }
  
      i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache);
      if (i != DECLINED) {
--- 534,559 ----
  	ap_table_set(resp_hdrs, "URI", proxy_location_reverse_map(r, datestr));
  
  /* check if NoCache directive on this host */
+   {
+     struct sockaddr_in *sin;
+ #ifdef INET6
+     struct sockaddr_in6 *sin6;
+ #endif
+ 
      for (i = 0; i < conf->nocaches->nelts; i++) {
! 	if (ncent[i].name != NULL && strstr(desthost, ncent[i].name))
! 	    nocache++;
! 	if (ncent[i].name != NULL && strcmp(ncent[i].name, "*") == 0)
! 	    nocache++;
! 	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++;
! 	    }
! 	}
      }
+   }
  
      i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache);
      if (i != DECLINED) {
Index: apache13/src/modules/proxy/proxy_util.c
diff -c apache13/src/modules/proxy/proxy_util.c:1.1.1.3 apache13/src/modules/proxy/proxy_util.c:1.5
*** apache13/src/modules/proxy/proxy_util.c:1.1.1.3	Thu Mar 25 03:14:35 1999
--- apache13/src/modules/proxy/proxy_util.c	Thu Mar 25 04:03:18 1999
***************
*** 1228,1249 ****
      return host != NULL && strstr(host, This->name) != NULL;
  }
  
! int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r)
  {
      int i;
  
      ap_hard_timeout("proxy connect", r);
      do {
! 	i = connect(sock, (struct sockaddr *) addr, sizeof(struct sockaddr_in));
  #ifdef WIN32
  	if (i == SOCKET_ERROR)
  	    errno = WSAGetLastError();
  #endif /* WIN32 */
      } while (i == -1 && errno == EINTR);
      if (i == -1) {
  	ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
! 		     "proxy connect to %s port %d failed",
! 		     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
      }
      ap_kill_timeout(r);
  
--- 1228,1254 ----
      return host != NULL && strstr(host, This->name) != NULL;
  }
  
! int ap_proxy_doconnect(int sock, struct sockaddr *addr, request_rec *r)
  {
      int i;
  
      ap_hard_timeout("proxy connect", r);
      do {
! 	i = connect(sock, addr, addr->sa_len);
  #ifdef WIN32
  	if (i == SOCKET_ERROR)
  	    errno = WSAGetLastError();
  #endif /* WIN32 */
      } while (i == -1 && errno == EINTR);
      if (i == -1) {
+ 	char hostnamebuf[MAXHOSTNAMELEN];
+ 	char portnamebuf[MAXHOSTNAMELEN];
+ 	getnameinfo(addr, addr->sa_len, hostnamebuf, sizeof(hostnamebuf),
+ 		portnamebuf, sizeof(portnamebuf),
+ 		NI_NUMERICHOST | NI_NUMERICSERV);
  	ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
! 		     "proxy connect to %s port %s failed",
! 		     hostnamebuf, portnamebuf);
      }
      ap_kill_timeout(r);
  
Index: apache13/src/modules/standard/mod_access.c
diff -c apache13/src/modules/standard/mod_access.c:1.1.1.2 apache13/src/modules/standard/mod_access.c:1.5
*** apache13/src/modules/standard/mod_access.c:1.1.1.2	Tue Jan 12 13:35:33 1999
--- apache13/src/modules/standard/mod_access.c	Tue Jan 12 14:29:39 1999
***************
*** 73,79 ****
      T_ALL,
      T_IP,
      T_HOST,
!     T_FAIL
  };
  
  typedef struct {
--- 73,82 ----
      T_ALL,
      T_IP,
      T_HOST,
!     T_FAIL,
! #ifdef INET6
!     T_IP6,
! #endif
  };
  
  typedef struct {
***************
*** 81,89 ****
      union {
  	char *from;
  	struct {
! 	    unsigned long net;
! 	    unsigned long mask;
  	} ip;
      } x;
      enum allowdeny_type type;
  } allowdeny;
--- 84,98 ----
      union {
  	char *from;
  	struct {
! 	    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;
***************
*** 166,254 ****
  
      }
      else if ((s = strchr(where, '/'))) {
! 	unsigned long mask;
  
! 	a->type = T_IP;
  	/* trample on where, we won't be using it any more */
  	*s++ = '\0';
  
! 	if (!is_ip(where)
! 	    || (a->x.ip.net = ap_inet_addr(where)) == INADDR_NONE) {
  	    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)) {
  	    a->type = T_FAIL;
! 	    return "syntax error in mask portion of network/netmask";
  	}
! 	/* is it in /a.b.c.d form? */
! 	if (strchr(s, '.')) {
! 	    mask = ap_inet_addr(s);
! 	    if (mask == INADDR_NONE) {
  		a->type = T_FAIL;
  		return "syntax error in mask portion of network/netmask";
  	    }
! 	}
! 	else {
! 	    /* assume it's in /nnn form */
! 	    mask = atoi(s);
! 	    if (mask > 32 || mask <= 0) {
  		a->type = T_FAIL;
! 		return "invalid mask in network/netmask";
  	    }
! 	    mask = 0xFFFFFFFFUL << (32 - mask);
! 	    mask = htonl(mask);
! 	}
! 	a->x.ip.mask = mask;
  
!     }
!     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 = 0;
! 	a->x.ip.mask = 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 |= octet << shift;
- 	    a->x.ip.mask |= 0xFFUL << shift;
- 	    s = t;
- 	    shift -= 8;
  	}
- 	a->x.ip.net = ntohl(a->x.ip.net);
- 	a->x.ip.mask = ntohl(a->x.ip.mask);
      }
      else {
  	a->type = T_HOST;
      }
  
--- 175,394 ----
  
      }
      else if ((s = strchr(where, '/'))) {
! 	struct addrinfo hints, *resnet, *resmask;
! 	struct sockaddr_storage net, mask;
! 	int error;
! 	char *p;
! 	int justdigits;
  
! 	a->type = T_FAIL;	/*just in case*/
  	/* trample on where, we won't be using it any more */
  	*s++ = '\0';
+ 
+ 	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_flags = AI_NUMERICHOST;	/*don't resolve*/
! 	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";
  	}
+ 	if (resnet->ai_next) {
+ 	    freeaddrinfo(resnet);
+ 	    a->type = T_FAIL;
+ 	    return "network/netmask resolved to multiple addresses";
+ 	}
+ 	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";
  	}
! 
! 	if (!justdigits) {
! 	    memset(&hints, 0, sizeof(hints));
! 	    hints.ai_family = PF_UNSPEC;
! 	    hints.ai_flags = AI_NUMERICHOST;	/*don't resolve*/
! 	    resmask = NULL;
! 	    error = getaddrinfo(s, NULL, &hints, &resmask);
! 	    if (error || !resmask) {
! 		if (resmask)
! 		    freeaddrinfo(resmask);
  		a->type = T_FAIL;
  		return "syntax error in mask portion of network/netmask";
  	    }
! 	    if (resmask->ai_next) {
! 		freeaddrinfo(resmask);
  		a->type = T_FAIL;
! 		return "network/netmask resolved to multiple addresses";
  	    }
! 	    memcpy(&mask, resmask->ai_addr, resmask->ai_addrlen);
! 	    freeaddrinfo(resmask);
  
! 	    if (net.ss_family != mask.ss_family) {
  		a->type = T_FAIL;
! 		return "network/netmask resolved to different address family";
  	    }
! 
! 	    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
  	    }
! 	} 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_addr8[i] = 0xff;
! 		}
! 		if (mask % 8)
! 		    a->x.ip6.mask6.s6_addr8[i] = 0xff << (8 - (mask % 8));
! 		break;
! 	      }
! #endif
  	    }
  	}
      }
      else {
+ 	struct addrinfo hints, *res;
+ 	struct sockaddr_storage ss;
+ 	int error;
+ 
+ 	a->type = T_FAIL;	/*just in case*/
+ 
+ 	/* IPv4/v6 numeric address */
+ 	memset(&hints, 0, sizeof(hints));
+ 	hints.ai_family = PF_UNSPEC;
+ 	hints.ai_flags = AI_NUMERICHOST;	/*don't resolve*/
+ 	res = NULL;
+ 	error = getaddrinfo(where, NULL, &hints, &res);
+ 	if (error || !res) {
+ 	    if (res)
+ 		freeaddrinfo(res);
+ 	    /* try legacy a.b.c. form */
+ 	    goto legacy;
+ 	}
+ 	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;
+ 
+ legacy:
+ 	/* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
+ 	if (ap_isdigit(*where) && is_ip(where)) {
+ 	    int shift;
+ 	    char *t;
+ 	    int octet;
+ 
+ 	    a->type = T_IP;
+ 	    /* parse components */
+ 	    s = where;
+ 	    a->x.ip.net.s_addr = 0;
+ 	    a->x.ip.mask.s_addr = 0;
+ 	    shift = 24;
+ 	    while (*s) {
+ 		t = s;
+ 		if (!ap_isdigit(*t)) {
+ 		    a->type = T_FAIL;
+ 		    return "invalid ip address";
+ 		}
+ 		while (ap_isdigit(*t)) {
+ 		    ++t;
+ 		}
+ 		if (*t == '.') {
+ 		    *t++ = 0;
+ 		}
+ 		else if (*t) {
+ 		    a->type = T_FAIL;
+ 		    return "invalid ip address";
+ 		}
+ 		if (shift < 0) {
+ 		    return "invalid ip address, only 4 octets allowed";
+ 		}
+ 		octet = atoi(s);
+ 		if (octet < 0 || octet > 255) {
+ 		    a->type = T_FAIL;
+ 		    return "each octet must be between 0 and 255 inclusive";
+ 		}
+ 		a->x.ip.net.s_addr |= octet << shift;
+ 		a->x.ip.mask.s_addr |= 0xFFUL << shift;
+ 		s = t;
+ 		shift -= 8;
+ 	    }
+ 	    a->x.ip.net.s_addr = ntohl(a->x.ip.net.s_addr);
+ 	    a->x.ip.mask.s_addr = ntohl(a->x.ip.mask.s_addr);
+ 	}
  	a->type = T_HOST;
      }
  
***************
*** 314,325 ****
  	    return 1;
  
  	case T_IP:
! 	    if (ap[i].x.ip.net != INADDR_NONE
! 		&& (r->connection->remote_addr.sin_addr.s_addr
! 		    & ap[i].x.ip.mask) == ap[i].x.ip.net) {
! 		return 1;
  	    }
  	    break;
  
  	case T_HOST:
  	    if (!gothost) {
--- 454,520 ----
  	    return 1;
  
  	case T_IP:
! 	    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 ((((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr.s6_addr32[3]
! 			& 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;
! 	    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;
! 		masked.s6_addr32[0] = 0;
! 		masked.s6_addr32[1] = 0;
! 		masked.s6_addr16[5] = 0;
! 		masked.s6_addr16[6] = 0xffff;
! 		masked.s6_addr32[3] =
! 		    ((struct sockaddr_in *)&r->connection->remote_addr)->sin_addr.s_addr;
! 		masked.s6_addr32[0] &= ap[i].x.ip6.mask6.s6_addr32[0];
! 		masked.s6_addr32[1] &= ap[i].x.ip6.mask6.s6_addr32[1];
! 		masked.s6_addr32[2] &= ap[i].x.ip6.mask6.s6_addr32[2];
! 		masked.s6_addr32[3] &= ap[i].x.ip6.mask6.s6_addr32[3];
! 		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));
! 		masked.s6_addr32[0] &= ap[i].x.ip6.mask6.s6_addr32[0];
! 		masked.s6_addr32[1] &= ap[i].x.ip6.mask6.s6_addr32[1];
! 		masked.s6_addr32[2] &= ap[i].x.ip6.mask6.s6_addr32[2];
! 		masked.s6_addr32[3] &= ap[i].x.ip6.mask6.s6_addr32[3];
! 		if (memcmp(&masked, &ap[i].x.ip6.net6, sizeof(&masked)) == 0)
! 		    return 1;
! 		break;
  	    }
  	    break;
+ 	  }
+ #endif
  
  	case T_HOST:
  	    if (!gothost) {
Index: apache13/src/support/ab.c
diff -c apache13/src/support/ab.c:1.1.1.3 apache13/src/support/ab.c:1.5
*** apache13/src/support/ab.c:1.1.1.3	Thu Mar 25 03:15:10 1999
--- apache13/src/support/ab.c	Thu Mar 25 04:03:20 1999
***************
*** 174,180 ****
  char *postdata;			/* *buffer containing data from postfile */
  int postlen = 0;		/* length of data to be POSTed */
  char content_type[1024];	/* content type to put in POST header */
! int port = 80;			/* port number */
  
  int use_html = 0;		/* use html in the report */
  char *tablestring;
--- 174,180 ----
  char *postdata;			/* *buffer containing data from postfile */
  int postlen = 0;		/* length of data to be POSTed */
  char content_type[1024];	/* content type to put in POST header */
! char *port = "80";		/* port number */
  
  int use_html = 0;		/* use html in the report */
  char *tablestring;
***************
*** 206,212 ****
  struct data *stats;		/* date for each request */
  
  fd_set readbits, writebits;	/* bits for select */
! struct sockaddr_in server;	/* server addr structure */
  
  /* --------------------------------------------------------- */
  
--- 206,212 ----
  struct data *stats;		/* date for each request */
  
  fd_set readbits, writebits;	/* bits for select */
! struct sockaddr_storage server;      /* server addr structure */
  
  /* --------------------------------------------------------- */
  
***************
*** 282,288 ****
      printf("\r                                                                           \r");
      printf("Server Software:        %s\n", servername);
      printf("Server Hostname:        %s\n", hostname);
!     printf("Server Port:            %d\n", port);
      printf("\n");
      printf("Document Path:          %s\n", path);
      printf("Document Length:        %d bytes\n", doclen);
--- 282,288 ----
      printf("\r                                                                           \r");
      printf("Server Software:        %s\n", servername);
      printf("Server Hostname:        %s\n", hostname);
!     printf("Server Port:            %s\n", port);
      printf("\n");
      printf("Document Path:          %s\n", path);
      printf("Document Length:        %d bytes\n", doclen);
***************
*** 477,503 ****
      c->cbx = 0;
      c->gotheader = 0;
  
!     c->fd = socket(AF_INET, SOCK_STREAM, 0);
      if (c->fd < 0)
  	err("socket");
  
      nonblock(c->fd);
      gettimeofday(&c->start, 0);
  
!     if (connect(c->fd, (struct sockaddr *) &server, sizeof(server)) < 0) {
! 	if (errno == EINPROGRESS) {
! 	    c->state = STATE_CONNECTING;
! 	    FD_SET(c->fd, &writebits);
! 	    return;
! 	}
! 	else {
! 	    close(c->fd);
! 	    err_conn++;
! 	    if (bad++ > 10) {
! 		err("\nTest aborted after 10 failures\n\n");
! 	    }
! 	    start_connect(c);
! 	}
      }
  
      /* connected first time */
--- 477,503 ----
      c->cbx = 0;
      c->gotheader = 0;
  
!     c->fd = socket(server.ss_family, SOCK_STREAM, 0);
      if (c->fd < 0)
  	err("socket");
  
      nonblock(c->fd);
      gettimeofday(&c->start, 0);
  
!     if (connect(c->fd, (struct sockaddr *) &server, server.ss_len) < 0) {
!         if (errno == EINPROGRESS) {
!             c->state = STATE_CONNECTING;
!             FD_SET(c->fd, &writebits);
!             return;
!         }
!         else {
!             close(c->fd);
!             err_conn++;
!             if (bad++ > 10) {
!                 err("\nTest aborted after 10 failures\n\n");
!             }
!             start_connect(c);
!         }
      }
  
      /* connected first time */
***************
*** 710,723 ****
      }
  
      {
! 	/* get server information */
! 	struct hostent *he;
! 	he = gethostbyname(hostname);
! 	if (!he)
! 	    err("bad hostname");
! 	server.sin_family = he->h_addrtype;
! 	server.sin_port = htons(port);
! 	server.sin_addr.s_addr = ((unsigned long *) (he->h_addr_list[0]))[0];
      }
  
      con = malloc(concurrency * sizeof(struct connection));
--- 710,726 ----
      }
  
      {
!         /* get server information */
! 	struct addrinfo hints, *res;
! 	int error;
! 
! 	memset(&hints, 0, sizeof(hints));
! 	hints.ai_family = AF_UNSPEC;
! 	error = getaddrinfo(hostname, port, &hints, &res);
! 	if (error)
! 		err("bad hostname");
! 	memcpy(&server, res->ai_addr, res->ai_addrlen);
! 	freeaddrinfo(res);
      }
  
      con = malloc(concurrency * sizeof(struct connection));
***************
*** 881,887 ****
      *cp = '\0';
      strcpy(hostname, h);
      if (p != NULL)
! 	port = atoi(p);
      return 0;
  }
  
--- 884,890 ----
      *cp = '\0';
      strcpy(hostname, h);
      if (p != NULL)
!         port = strdup(p);
      return 0;
  }
  
***************
*** 1007,1009 ****
--- 1010,1016 ----
  
      exit(0);
  }
+ 
+ #ifdef NEED_GETADDRINFO
+ #include "../main/getaddrinfo.c"
+ #endif
Index: apache13/src/support/logresolve.c
diff -c apache13/src/support/logresolve.c:1.1.1.1 apache13/src/support/logresolve.c:1.3
*** apache13/src/support/logresolve.c:1.1.1.1	Fri Oct  2 13:30:39 1998
--- apache13/src/support/logresolve.c	Sun Jan 17 13:25:41 1999
***************
*** 48,54 ****
  #include <arpa/inet.h>
  #endif
  
! static void cgethost(struct in_addr ipnum, char *string, int check);
  static int getline(char *s, int n);
  static void stats(FILE *output);
  
--- 48,54 ----
  #include <arpa/inet.h>
  #endif
  
! static void cgethost(struct sockaddr *sa, char *string, int check);
  static int getline(char *s, int n);
  static void stats(FILE *output);
  
***************
*** 85,91 ****
   */
  
  struct nsrec {
!     struct in_addr ipnum;
      char *hostname;
      int noname;
      struct nsrec *next;
--- 85,91 ----
   */
  
  struct nsrec {
!     struct sockaddr_storage addr;
      char *hostname;
      int noname;
      struct nsrec *next;
***************
*** 116,132 ****
   * IP numbers with their IP number as hostname, setting noname flag
   */
  
! static void cgethost (struct in_addr ipnum, char *string, int check)
  {
      struct nsrec **current, *new;
-     struct hostent *hostdata;
      char *name;
  
!     current = &nscache[((ipnum.s_addr + (ipnum.s_addr >> 8) +
! 			 (ipnum.s_addr >> 16) + (ipnum.s_addr >> 24)) % BUCKETS)];
  
!     while (*current != NULL && ipnum.s_addr != (*current)->ipnum.s_addr)
  	current = &(*current)->next;
  
      if (*current == NULL) {
  	cachesize++;
--- 116,157 ----
   * IP numbers with their IP number as hostname, setting noname flag
   */
  
! static void cgethost (struct sockaddr *sa, char *string, int check)
  {
+     u_int32_t hashval;
+     struct sockaddr_in *sin;
+ #ifdef INET6
+     struct sockaddr_in6 *sin6;
+ #endif
      struct nsrec **current, *new;
      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 = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr32[3];
+ 	break;
+ #endif
+     default:
+ 	hashval = 0;
+ 	break;
+     }
  
!     current = &nscache[((hashval + (hashval >> 8) +
! 			 (hashval >> 16) + (hashval >> 24)) % BUCKETS)];
  
!     while (*current) {
! 	if (sa->sa_len == (*current)->addr.ss_len
! 	 && memcmp(sa, &(*current)->addr, sa->sa_len) == 0) {
! 	    break;
! 	}
! 
  	current = &(*current)->next;
+     }
  
      if (*current == NULL) {
  	cachesize++;
***************
*** 139,183 ****
  	*current = new;
  	new->next = NULL;
  
! 	new->ipnum = ipnum;
  
! 	hostdata = gethostbyaddr((const char *) &ipnum, sizeof(struct in_addr),
! 				 AF_INET);
! 	if (hostdata == NULL) {
! 	    if (h_errno > MAX_ERR)
! 		errors[UNKNOWN_ERR]++;
! 	    else
! 		errors[h_errno]++;
! 	    new->noname = h_errno;
! 	    name = strdup(inet_ntoa(ipnum));
! 	}
! 	else {
! 	    new->noname = 0;
! 	    name = strdup(hostdata->h_name);
! 	    if (check) {
! 		if (name == NULL) {
! 		    perror("strdup");
! 		    fprintf(stderr, "Insufficient memory\n");
! 		    exit(1);
! 		}
! 		hostdata = gethostbyname(name);
! 		if (hostdata != NULL) {
! 		    char **hptr;
! 
! 		    for (hptr = hostdata->h_addr_list; *hptr != NULL; hptr++)
! 			if (((struct in_addr *) (*hptr))->s_addr == ipnum.s_addr)
! 			    break;
! 		    if (*hptr == NULL)
! 			hostdata = NULL;
  		}
! 		if (hostdata == NULL) {
! 		    fprintf(stderr, "Bad host: %s != %s\n", name,
! 			    inet_ntoa(ipnum));
! 		    new->noname = NO_REVERSE;
! 		    free(name);
! 		    name = strdup(inet_ntoa(ipnum));
! 		    errors[NO_REVERSE]++;
! 		}
  	    }
  	}
  	new->hostname = name;
--- 164,197 ----
  	*current = new;
  	new->next = NULL;
  
! 	memcpy(&new->addr, sa, sa->sa_len);
  
! 	new->noname = getnameinfo(sa, sa->sa_len,
! 		    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 = AF_UNSPEC;
! 	    error = getaddrinfo(hostnamebuf, NULL, &hints, &res);
! 	    if (!error) {
! 		while (res) {
! 		    if (sa->sa_len == res->ai_addrlen
! 		     && memcmp(sa, res->ai_addr, sa->sa_len) == 0)
! 			break;
! 		    res = res->ai_next;
  		}
! 		if (!res)
! 		    error++;
! 	    }
! 	    if (error) {
! 		getnameinfo(sa, sa->sa_len,
! 		    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;
***************
*** 205,210 ****
--- 219,225 ----
      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";
***************
*** 236,242 ****
  
      for (i = 0; i < BUCKETS; i++)
  	for (current = nscache[i]; current != NULL; current = current->next) {
! 	    ipstring = inet_ntoa(current->ipnum);
  	    if (current->noname == 0)
  		fprintf(output, "  %3d  %15s - %s\n", i, ipstring,
  			current->hostname);
--- 251,259 ----
  
      for (i = 0; i < BUCKETS; i++)
  	for (current = nscache[i]; current != NULL; current = current->next) {
! 	    getnameinfo((struct sockaddr *)&current->addr, current->addr.ss_len,
! 		    hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
! 	    ipstring = hostnamebuf;
  	    if (current->noname == 0)
  		fprintf(output, "  %3d  %15s - %s\n", i, ipstring,
  			current->hostname);
***************
*** 270,278 ****
  
  int main (int argc, char *argv[])
  {
-     struct in_addr ipnum;
      char *bar, hoststring[MAXDNAME + 1], line[MAXLINE], *statfile;
      int i, check;
  
      check = 0;
      statfile = NULL;
--- 287,296 ----
  
  int main (int argc, char *argv[])
  {
      char *bar, hoststring[MAXDNAME + 1], line[MAXLINE], *statfile;
      int i, check;
+     struct addrinfo hints, *res;
+     int error;
  
      check = 0;
      statfile = NULL;
***************
*** 311,318 ****
  	bar = strchr(line, ' ');
  	if (bar != NULL)
  	    *bar = '\0';
! 	ipnum.s_addr = inet_addr(line);
! 	if (ipnum.s_addr == 0xffffffffu) {
  	    if (bar != NULL)
  		*bar = ' ';
  	    puts(line);
--- 329,338 ----
  	bar = strchr(line, ' ');
  	if (bar != NULL)
  	    *bar = '\0';
! 	memset(&hints, 0, sizeof(hints));
! 	hints.ai_family = AF_UNSPEC;
! 	error = getaddrinfo(line, NULL, &hints, &res);
! 	if (error) {
  	    if (bar != NULL)
  		*bar = ' ';
  	    puts(line);
***************
*** 322,332 ****
  
  	resolves++;
  
! 	cgethost(ipnum, hoststring, check);
  	if (bar != NULL)
  	    printf("%s %s\n", hoststring, bar + 1);
  	else
  	    puts(hoststring);
      }
  
      if (statfile != NULL) {
--- 342,353 ----
  
  	resolves++;
  
! 	cgethost(res->ai_addr, hoststring, check);
  	if (bar != NULL)
  	    printf("%s %s\n", hoststring, bar + 1);
  	else
  	    puts(hoststring);
+ 	freeaddrinfo(res);
      }
  
      if (statfile != NULL) {
***************
*** 343,345 ****
--- 364,374 ----
  
      return (0);
  }
+ 
+ #ifdef NEED_GETADDRINFO
+ #include "../main/getaddrinfo.c"
+ #endif
+ 
+ #ifdef NEED_GETNAMEINFO
+ #include "../main/getnameinfo.c"
+ #endif
