diff --git a/config/c-library.m4 b/config/c-library.m4
index f482f9936cb6e003be90bb475b098c6ca1ad4754..bd632ed7cd36b6bb9f36c00403d4c3671a331fa3 100644
--- a/config/c-library.m4
+++ b/config/c-library.m4
@@ -1,5 +1,5 @@
 # Macros that test various C library quirks
-# $Header: /cvsroot/pgsql/config/c-library.m4,v 1.19 2003/05/22 16:39:26 tgl Exp $
+# $Header: /cvsroot/pgsql/config/c-library.m4,v 1.20 2003/06/12 07:36:51 momjian Exp $
 
 
 # PGAC_VAR_INT_TIMEZONE
@@ -87,11 +87,10 @@ AC_DEFUN([PGAC_UNION_SEMUN],
 
 # PGAC_STRUCT_SOCKADDR_UN
 # -----------------------
-# If `struct sockaddr_un' exists, define HAVE_STRUCT_SOCKADDR_UN. If
-# it is missing then one could define it as { short int sun_family;
-# char sun_path[108]; }. (Requires test for <sys/un.h>!)
+# If `struct sockaddr_un' exists, define HAVE_UNIX_SOCKETS.
+# (Requires test for <sys/un.h>!)
 AC_DEFUN([PGAC_STRUCT_SOCKADDR_UN],
-[AC_CHECK_TYPES([struct sockaddr_un], [], [],
+[AC_CHECK_TYPES([struct sockaddr_un], [AC_DEFINE(HAVE_UNIX_SOCKETS, 1, [Define to 1 if you have unix sockets.])], [],
 [#include <sys/types.h>
 #ifdef HAVE_SYS_UN_H
 #include <sys/un.h>
@@ -99,6 +98,18 @@ AC_DEFUN([PGAC_STRUCT_SOCKADDR_UN],
 ])])# PGAC_STRUCT_SOCKADDR_UN
 
 
+# PGAC_STRUCT_SOCKADDR_STORAGE
+# ----------------------------
+# If `struct sockaddr_storage' exists, define HAVE_STRUCT_SOCKADDR_STORAGE. If
+# it is missing then one could define it.
+AC_DEFUN([PGAC_STRUCT_SOCKADDR_STORAGE],
+[AC_CHECK_TYPES([struct sockaddr_storage], [], [],
+[#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+])])# PGAC_STRUCT_SOCKADDR_STORAGE
+
+
 # PGAC_STRUCT_ADDRINFO
 # -----------------------
 # If `struct addrinfo' exists, define HAVE_STRUCT_ADDRINFO.
diff --git a/configure b/configure
index 906e9b33b32efe9f456a18ed5ce7ec4e12276b8e..2056980885ac069d705c10f55484421fa2fe323f 100755
--- a/configure
+++ b/configure
@@ -9892,6 +9892,71 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_UNIX_SOCKETS 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for struct sockaddr_storage" >&5
+echo $ECHO_N "checking for struct sockaddr_storage... $ECHO_C" >&6
+if test "${ac_cv_type_struct_sockaddr_storage+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+if ((struct sockaddr_storage *) 0)
+  return 0;
+if (sizeof (struct sockaddr_storage))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_struct_sockaddr_storage=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_type_struct_sockaddr_storage=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_struct_sockaddr_storage" >&5
+echo "${ECHO_T}$ac_cv_type_struct_sockaddr_storage" >&6
+if test $ac_cv_type_struct_sockaddr_storage = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+_ACEOF
+
+
 fi
 
 echo "$as_me:$LINENO: checking for struct addrinfo" >&5
diff --git a/configure.in b/configure.in
index 5881542a4cf4868da45a792b960457ad6f39b86a..8ccff55630980891128a293a3f4a9547cbb57fed 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-dnl $Header: /cvsroot/pgsql/configure.in,v 1.258 2003/06/11 06:56:06 momjian Exp $
+dnl $Header: /cvsroot/pgsql/configure.in,v 1.259 2003/06/12 07:36:50 momjian Exp $
 dnl
 dnl Developers, please strive to achieve this order:
 dnl
@@ -789,6 +789,7 @@ PGAC_C_FUNCNAME_SUPPORT
 PGAC_STRUCT_TIMEZONE
 PGAC_UNION_SEMUN
 PGAC_STRUCT_SOCKADDR_UN
+PGAC_STRUCT_SOCKADDR_STORAGE
 PGAC_STRUCT_ADDRINFO
 
 AC_CHECK_TYPES([struct cmsgcred, struct fcred, struct sockcred], [], [],
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 2b0d2d65a8b9d00dad770c4e163736c3ad82ea89..46965e3bcb3acccc6f2cde27a0312e5c004b1f64 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.101 2003/04/25 03:28:55 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.102 2003/06/12 07:36:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -415,15 +415,13 @@ ClientAuthentication(Port *port)
 			 * out the less clueful good guys.
 			 */
 			{
-				const char *hostinfo = "localhost";
-#ifdef HAVE_IPV6
-				char	ip_hostinfo[INET6_ADDRSTRLEN];
-#else
-				char	ip_hostinfo[INET_ADDRSTRLEN];
-#endif
-				if (isAF_INETx(port->raddr.sa.sa_family) )
-					hostinfo = SockAddr_ntop(&port->raddr, ip_hostinfo,
-							   sizeof(ip_hostinfo), 1);
+				char	hostinfo[NI_MAXHOST];
+
+				getnameinfo(
+					(struct sockaddr *)&port->raddr.addr,
+					port->raddr.salen,
+					hostinfo, sizeof(hostinfo),
+					NULL, 0, NI_NUMERICHOST);
 
 				elog(FATAL,
 					"No pg_hba.conf entry for host %s, user %s, database %s",
@@ -464,7 +462,7 @@ ClientAuthentication(Port *port)
 					elog(FATAL, "pg_local_sendauth: can't do setsockopt: %m");
 			}
 #endif
-			if (port->raddr.sa.sa_family == AF_UNIX)
+			if (port->raddr.addr.ss_family == AF_UNIX)
 				sendAuthRequest(port, AUTH_REQ_SCM_CREDS);
 #endif
 			status = authident(port);
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 4310261a16bd94fa65b896df88009f1fdc33aef9..c277c90d1b9d6af34a054576cb9ea025b58803b1 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.102 2003/06/12 07:00:57 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.103 2003/06/12 07:36:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -542,9 +542,14 @@ static void
 parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
 {
 	int			line_number;
-	char	   *token;
-	char	   *db;
-	char	   *user;
+	char			*token;
+	char			*db;
+	char			*user;
+	struct addrinfo		*file_ip_addr = NULL, *file_ip_mask = NULL;
+	struct addrinfo		hints;
+	struct sockaddr_storage	*mask;
+	char 			*cidr_slash;
+	int			ret;
 
 	Assert(line != NIL);
 	line_number = lfirsti(line);
@@ -582,12 +587,11 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
 			port->auth_method == uaKrb5)
 			goto hba_syntax;
 
-		if (port->raddr.sa.sa_family != AF_UNIX)
+		if (port->raddr.addr.ss_family != AF_UNIX)
 			return;
 	}
 	else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0)
 	{
-		SockAddr file_ip_addr, mask;
 
 		if (strcmp(token, "hostssl") == 0)
 		{
@@ -618,26 +622,77 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
 			goto hba_syntax;
 		user = lfirst(line);
 
-		/* Read the IP address field. */
+		/* Read the IP address field. (with or without CIDR netmask) */
 		line = lnext(line);
 		if (!line)
 			goto hba_syntax;
 		token = lfirst(line);
 
-		if(SockAddr_pton(&file_ip_addr, token) < 0)
-			goto hba_syntax;
+		/* Check if it has a CIDR suffix and if so isolate it */
+		cidr_slash = index(token,'/');
+		if (cidr_slash)
+		{
+			*cidr_slash = '\0';
+		}
 
-		/* Read the mask field. */
-		line = lnext(line);
-		if (!line)
+		hints.ai_flags = AI_NUMERICHOST;
+		hints.ai_family = PF_UNSPEC;
+		hints.ai_socktype = 0;
+		hints.ai_protocol = 0;
+		hints.ai_addrlen = 0;
+		hints.ai_canonname = NULL;
+		hints.ai_addr = NULL;
+		hints.ai_next = NULL;
+
+		/* Get the IP address either way */
+		ret = getaddrinfo2(token, NULL, &hints, &file_ip_addr);
+		if (ret)
+		{
+			elog(LOG, "getaddrinfo2() returned %d", ret);
+			if (cidr_slash)
+			{
+				*cidr_slash = '/';
+			}
 			goto hba_syntax;
-		token = lfirst(line);
+		}
 
-		if(SockAddr_pton(&mask, token) < 0)
-			goto hba_syntax;
+		if (file_ip_addr->ai_family != port->raddr.addr.ss_family)
+		{
+			/* Wrong address family. */
+			freeaddrinfo2(hints.ai_family, file_ip_addr);
+			return;
+		}
 
-		if(file_ip_addr.sa.sa_family != mask.sa.sa_family)
-			goto hba_syntax;
+		/* Get the netmask */
+		if (cidr_slash)
+		{
+			*cidr_slash = '/';
+			if (SockAddr_cidr_mask(&mask, cidr_slash + 1,
+				file_ip_addr->ai_family) < 0)
+			{
+                               goto hba_syntax;
+			}
+		}
+		else
+		{
+			/* Read the mask field. */
+			line = lnext(line);
+			if (!line)
+				goto hba_syntax;
+			token = lfirst(line);
+
+			ret = getaddrinfo2(token, NULL, &hints, &file_ip_mask);
+			if (ret)
+			{
+				goto hba_syntax;
+			}
+			mask = (struct sockaddr_storage *)file_ip_mask->ai_addr;
+
+			if(file_ip_addr->ai_family != mask->ss_family)
+			{
+				goto hba_syntax;
+			}
+		}
 
 		/* Read the rest of the line. */
 		line = lnext(line);
@@ -648,9 +703,16 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
 			goto hba_syntax;
 
 		/* Must meet network restrictions */
-		if (!isAF_INETx(port->raddr.sa.sa_family) ||
-			!rangeSockAddr(&port->raddr, &file_ip_addr, &mask))
-			return;
+		if (!rangeSockAddr(&port->raddr.addr,
+			(struct sockaddr_storage *)file_ip_addr->ai_addr, mask))
+		{
+			goto hba_freeaddr;
+		}
+		freeaddrinfo2(hints.ai_family, file_ip_addr);
+		if (file_ip_mask)
+		{
+			freeaddrinfo2(hints.ai_family, file_ip_mask);
+		}
 	}
 	else
 		goto hba_syntax;
@@ -670,6 +732,16 @@ hba_syntax:
 		 line ? (const char *) lfirst(line) : "(end of line)");
 
 	*error_p = true;
+
+hba_freeaddr:
+	if (file_ip_addr)
+	{
+		freeaddrinfo2(hints.ai_family, file_ip_addr);
+	}
+	if (file_ip_mask)
+	{
+		freeaddrinfo2(hints.ai_family, file_ip_mask);
+	}
 	return;
 }
 
@@ -1106,10 +1178,8 @@ interpret_ident_response(char *ident_response,
  *	But iff we're unable to get the information from ident, return false.
  */
 static bool
-ident_inet(const struct in_addr remote_ip_addr,
-		   const struct in_addr local_ip_addr,
-		   const ushort remote_port,
-		   const ushort local_port,
+ident_inet(const SockAddr remote_addr,
+		   const SockAddr local_addr,
 		   char *ident_user)
 {
 	int			sock_fd,		/* File descriptor for socket on which we
@@ -1117,8 +1187,39 @@ ident_inet(const struct in_addr remote_ip_addr,
 				rc;				/* Return code from a locally called
 								 * function */
 	bool		ident_return;
+	char		remote_addr_s[NI_MAXHOST];
+	char		remote_port[NI_MAXSERV];
+	char		local_addr_s[NI_MAXHOST];
+	char		local_port[NI_MAXSERV];
+	char		ident_port[NI_MAXSERV];
+	struct addrinfo	*ident_serv = NULL, *la = NULL, hints;
+
+	/* Might look a little weird to first convert it to text and
+	 * then back to sockaddr, but it's protocol indepedant. */
+	getnameinfo((struct sockaddr *)&remote_addr.addr,
+		remote_addr.salen, remote_addr_s, sizeof(remote_addr_s),
+		remote_port, sizeof(remote_port),
+		NI_NUMERICHOST|NI_NUMERICSERV);
+	getnameinfo((struct sockaddr *)&local_addr.addr,
+		local_addr.salen, local_addr_s,	sizeof(local_addr_s),
+		local_port, sizeof(local_port),
+		NI_NUMERICHOST|NI_NUMERICSERV);
+
+	snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
+	hints.ai_flags = AI_NUMERICHOST;
+	hints.ai_family = remote_addr.addr.ss_family;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_protocol = 0;
+	hints.ai_addrlen = 0;
+	hints.ai_canonname = NULL;
+	hints.ai_addr = NULL;
+	hints.ai_next = NULL;
+	getaddrinfo2(remote_addr_s, ident_port, &hints, &ident_serv);
+	getaddrinfo2(local_addr_s, NULL, &hints, &la);
+	
+	sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
+		ident_serv->ai_protocol);
 
-	sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 	if (sock_fd == -1)
 	{
 		elog(LOG, "Failed to create socket on which to talk to Ident server: %m");
@@ -1126,42 +1227,27 @@ ident_inet(const struct in_addr remote_ip_addr,
 	}
 	else
 	{
-		struct sockaddr_in ident_server;
-		struct sockaddr_in la;
-
-		/*
-		 * Socket address of Ident server on the system from which client
-		 * is attempting to connect to us.
-		 */
-		ident_server.sin_family = AF_INET;
-		ident_server.sin_port = htons(IDENT_PORT);
-		ident_server.sin_addr = remote_ip_addr;
-
 		/*
 		 * Bind to the address which the client originally contacted,
 		 * otherwise the ident server won't be able to match up the right
 		 * connection. This is necessary if the PostgreSQL server is
 		 * running on an IP alias.
 		 */
-		memset(&la, 0, sizeof(la));
-		la.sin_family = AF_INET;
-		la.sin_addr = local_ip_addr;
-		rc = bind(sock_fd, (struct sockaddr *) & la, sizeof(la));
+
+		rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
 		if (rc == 0)
 		{
-			rc = connect(sock_fd,
-			   (struct sockaddr *) & ident_server, sizeof(ident_server));
+			rc = connect(sock_fd, ident_serv->ai_addr, 
+				ident_serv->ai_addrlen);
 		}
 		if (rc != 0)
 		{
-			/* save_errno is in case inet_ntoa changes errno */
-			int			save_errno = errno;
+			int	save_errno = errno;
 
 			elog(LOG, "Unable to connect to Ident server on the host which is "
 				 "trying to connect to Postgres "
-				 "(IP address %s, Port %d): %s",
-				 inet_ntoa(remote_ip_addr), IDENT_PORT,
-				 strerror(save_errno));
+				 "(Address %s, Port %s): %s", remote_addr_s,
+				 ident_port, strerror(save_errno));
 			ident_return = false;
 		}
 		else
@@ -1169,8 +1255,8 @@ ident_inet(const struct in_addr remote_ip_addr,
 			char		ident_query[80];
 
 			/* The query we send to the Ident server */
-			snprintf(ident_query, sizeof(ident_query), "%d,%d\n",
-					 ntohs(remote_port), ntohs(local_port));
+			snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
+				remote_port, local_port);
 			/* loop in case send is interrupted */
 			do
 			{
@@ -1181,10 +1267,9 @@ ident_inet(const struct in_addr remote_ip_addr,
 				int			save_errno = errno;
 
 				elog(LOG, "Unable to send query to Ident server on the host which is "
-					 "trying to connect to Postgres (Host %s, Port %d), "
+					 "trying to connect to Postgres (Host %s, Port %s), "
 					 "even though we successfully connected to it: %s",
-					 inet_ntoa(remote_ip_addr), IDENT_PORT,
-					 strerror(save_errno));
+					 remote_addr_s, ident_port, strerror(save_errno));
 				ident_return = false;
 			}
 			else
@@ -1199,9 +1284,9 @@ ident_inet(const struct in_addr remote_ip_addr,
 
 					elog(LOG, "Unable to receive response from Ident server "
 						 "on the host which is "
-					 "trying to connect to Postgres (Host %s, Port %d), "
+					 "trying to connect to Postgres (Host %s, Port %s), "
 						 "even though we successfully sent our query to it: %s",
-						 inet_ntoa(remote_ip_addr), IDENT_PORT,
+						 remote_addr_s, ident_port,
 						 strerror(save_errno));
 					ident_return = false;
 				}
@@ -1215,6 +1300,8 @@ ident_inet(const struct in_addr remote_ip_addr,
 			closesocket(sock_fd);
 		}
 	}
+	freeaddrinfo2(hints.ai_family, la);
+	freeaddrinfo2(hints.ai_family, ident_serv);
 	return ident_return;
 }
 
@@ -1371,13 +1458,13 @@ authident(hbaPort *port)
 {
 	char		ident_user[IDENT_USERNAME_MAX + 1];
 
-	switch (port->raddr.sa.sa_family)
+	switch (port->raddr.addr.ss_family)
 	{
 		case AF_INET:
-			if (!ident_inet(port->raddr.in.sin_addr,
-							port->laddr.in.sin_addr,
-							port->raddr.in.sin_port,
-							port->laddr.in.sin_port, ident_user))
+#ifdef	HAVE_IPV6
+		case AF_INET6:
+#endif
+			if (!ident_inet(port->raddr, port->laddr, ident_user))
 				return STATUS_ERROR;
 			break;
 		case AF_UNIX:
diff --git a/src/backend/libpq/ip.c b/src/backend/libpq/ip.c
index 203317be4eb77b186f6ed376bc9047929fe6c184..59bee56e212e026ed5e4bde6cbbbfd2e26a9dda8 100644
--- a/src/backend/libpq/ip.c
+++ b/src/backend/libpq/ip.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.11 2003/06/12 07:00:57 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.12 2003/06/12 07:36:51 momjian Exp $
  *
  * This file and the IPV6 implementation were initially provided by
  * Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design
@@ -36,20 +36,19 @@
 #include "libpq/ip.h"
 
 
-static int   rangeSockAddrAF_INET(const SockAddr *addr,
-								  const SockAddr *netaddr,
-								  const SockAddr *netmask);
-
+static int	rangeSockAddrAF_INET(const struct sockaddr_in *addr,
+			const struct sockaddr_in *netaddr,
+			const struct sockaddr_in *netmask);
 #ifdef HAVE_IPV6
-static int   rangeSockAddrAF_INET6(const SockAddr *addr,
-								   const SockAddr *netaddr,
-								   const SockAddr *netmask);
-static void  convSockAddr6to4(const SockAddr *src, SockAddr *dst);
+static int	rangeSockAddrAF_INET6(const struct sockaddr_in6 *addr,
+			const struct sockaddr_in6 *netaddr,
+			const struct sockaddr_in6 *netmask);
 #endif
 
-#ifdef HAVE_UNIX_SOCKETS
-static int getaddrinfo_unix(const char *path, const struct addrinfo *hintsp,
-							struct addrinfo **result);
+#ifdef	HAVE_UNIX_SOCKETS
+static int	getaddrinfo_unix(const char *path,
+			const struct addrinfo *hintsp,
+			struct addrinfo **result);
 #endif
 
 
@@ -127,6 +126,11 @@ getaddrinfo_unix(const char *path, const struct addrinfo *hintsp,
 
 	MemSet(&hints, 0, sizeof(hints));
 
+	if (strlen(path) >= sizeof(unp->sun_path))
+	{
+		return EAI_FAIL;
+	}
+
 	if (hintsp == NULL)
 	{
 		hints.ai_family = AF_UNIX;
@@ -141,7 +145,7 @@ getaddrinfo_unix(const char *path, const struct addrinfo *hintsp,
 	if (hints.ai_family != AF_UNIX)
 	{
 		/* shouldn't have been called */
-		return EAI_ADDRFAMILY;
+		return EAI_FAIL;
 	}
 
 	aip = calloc(1, sizeof(struct addrinfo));
@@ -166,8 +170,6 @@ getaddrinfo_unix(const char *path, const struct addrinfo *hintsp,
 	aip->ai_addr = (struct sockaddr *) unp;
 	aip->ai_addrlen = sizeof(struct sockaddr_un);
 
-	if (strlen(path) >= sizeof(unp->sun_path))
-		return EAI_SERVICE;
 	strcpy(unp->sun_path, path);
 
 #if SALEN
@@ -178,121 +180,110 @@ getaddrinfo_unix(const char *path, const struct addrinfo *hintsp,
 }
 #endif   /* HAVE_UNIX_SOCKETS */
 
-/* ----------
- * SockAddr_ntop - set IP address string from SockAddr
- *
- * parameters...  sa	: SockAddr union
- *				  dst	: buffer for address string
- *				  cnt	: sizeof dst
- *				  v4conv: non-zero: if address is IPv4 mapped IPv6 address then
- *						  convert to IPv4 address.
- * returns... pointer to dst
- * if sa.sa_family is not AF_INET or AF_INET6 dst is set as empy string.
- * ----------
- */
-char *
-SockAddr_ntop(const SockAddr *sa, char *dst, size_t cnt, int v4conv)
+
+int
+rangeSockAddr(const struct sockaddr_storage *addr,
+		const struct sockaddr_storage *netaddr,
+		const struct sockaddr_storage *netmask)
 {
-	switch (sa->sa.sa_family)
-	{
-		case AF_INET:
+	if (addr->ss_family == AF_INET)
+		return rangeSockAddrAF_INET((struct sockaddr_in *)addr,
+			(struct sockaddr_in *)netaddr,
+			(struct sockaddr_in *)netmask);
 #ifdef HAVE_IPV6
-			inet_ntop(AF_INET, &sa->in.sin_addr, dst, cnt);
-#else
-			StrNCpy(dst, inet_ntoa(sa->in.sin_addr), cnt);
+	else if (addr->ss_family == AF_INET6)
+		return rangeSockAddrAF_INET6((struct sockaddr_in6 *)addr,
+			(struct sockaddr_in6 *)netaddr,
+			(struct sockaddr_in6 *)netmask);
 #endif
-			break;
-#ifdef HAVE_IPV6
-		case AF_INET6:
-			inet_ntop(AF_INET6, &sa->in6.sin6_addr, dst, cnt);
-			if (v4conv && IN6_IS_ADDR_V4MAPPED(&sa->in6.sin6_addr))
-				strcpy(dst, dst + 7);
-			break;
-#endif
-		default:
-			dst[0] = '\0';
-			break;
-	}
-	return dst;
+	else
+		return 0;
 }
 
-
 /*
- *	SockAddr_pton - IPv6 pton
+ *  SockAddr_cidr_mask - make a network mask of the appropriate family
+ *    and required number of significant bits
+ *
+ * Note: Returns a static pointer for the mask, so it's not thread safe,
+ *       and a second call will overwrite the data.
  */
 int
-SockAddr_pton(SockAddr *sa, const char *src)
+SockAddr_cidr_mask(struct sockaddr_storage **mask, char *numbits, int family)
 {
-	int			family = AF_INET;
+	long			bits;
+	char			*endptr;
+static	struct sockaddr_storage	sock;
+	struct sockaddr_in	mask4;
+#ifdef	HAVE_IPV6
+	struct sockaddr_in6	mask6;
+#endif
+
+	bits = strtol(numbits, &endptr, 10);
+
+	if (*numbits == '\0' || *endptr != '\0')
+	{
+		return -1;
+	}
 
+	if ((bits < 0) || (family == AF_INET && bits > 32)
 #ifdef HAVE_IPV6
-	if (strchr(src, ':'))
-		family = AF_INET6;
+		|| (family == AF_INET6 && bits > 128)
 #endif
+		)
+	{
+		return -1;
+	}
 
-	sa->sa.sa_family = family;
+	*mask = &sock;
 
 	switch (family)
 	{
 		case AF_INET:
-#ifdef HAVE_IPV6
-			return inet_pton(AF_INET, src, &sa->in.sin_addr);
-#else
-			return inet_aton(src, &sa->in.sin_addr);
-#endif
-
+			mask4.sin_addr.s_addr = 
+				htonl((0xffffffffUL << (32 - bits))
+					& 0xffffffffUL);
+			memcpy(&sock, &mask4, sizeof(mask4));			
+			break;
 #ifdef HAVE_IPV6
 		case AF_INET6:
-			return inet_pton(AF_INET6, src, &sa->in6.sin6_addr);
+		{
+			int i;
+			
+			for (i = 0; i < 16; i++)
+			{
+				if (bits <= 0)
+				{
+					mask6.sin6_addr.s6_addr[i] = 0;
+				}
+				else if (bits >= 8)
+				{
+					mask6.sin6_addr.s6_addr[i] = 0xff;
+				}
+				else
+				{
+					mask6.sin6_addr.s6_addr[i] =
+						(0xff << (8 - bits)) & 0xff;
+				}
+				bits -= 8;
+			}
+			memcpy(&sock, &mask6, sizeof(mask6));
 			break;
+		}
 #endif
 		default:
 			return -1;
 	}
-}
 
-
-/*
- *	isAF_INETx - check to see if sa is AF_INET or AF_INET6
- */
-int
-isAF_INETx(const int family)
-{
-	if (family == AF_INET
-#ifdef HAVE_IPV6
-		|| family == AF_INET6
-#endif
-		)
-		return 1;
-	else
-		return 0;
+	sock.ss_family = family;
+	return 0;
 }
 
-
 int
-rangeSockAddr(const SockAddr *addr, const SockAddr *netaddr,
-			  const SockAddr *netmask)
+rangeSockAddrAF_INET(const struct sockaddr_in *addr, const struct sockaddr_in *netaddr,
+					 const struct sockaddr_in *netmask)
 {
-	if (addr->sa.sa_family == AF_INET)
-		return rangeSockAddrAF_INET(addr, netaddr, netmask);
-#ifdef HAVE_IPV6
-	else if (addr->sa.sa_family == AF_INET6)
-		return rangeSockAddrAF_INET6(addr, netaddr, netmask);
-#endif
-	else
-		return 0;
-}
-
-static int
-rangeSockAddrAF_INET(const SockAddr *addr, const SockAddr *netaddr,
-					 const SockAddr *netmask)
-{
-	if (addr->sa.sa_family != AF_INET ||
-		netaddr->sa.sa_family != AF_INET ||
-		netmask->sa.sa_family != AF_INET)
-		return 0;
-	if (((addr->in.sin_addr.s_addr ^ netaddr->in.sin_addr.s_addr) &
-		 netmask->in.sin_addr.s_addr) == 0)
+	if (((addr->sin_addr.s_addr ^ netaddr->sin_addr.s_addr) &
+		 netmask->sin_addr.s_addr) == 0)
 		return 1;
 	else
 		return 0;
@@ -300,46 +291,22 @@ rangeSockAddrAF_INET(const SockAddr *addr, const SockAddr *netaddr,
 
 
 #ifdef HAVE_IPV6
-
-static int
-rangeSockAddrAF_INET6(const SockAddr *addr, const SockAddr *netaddr,
-					  const SockAddr *netmask)
+int
+rangeSockAddrAF_INET6(const struct sockaddr_in6 *addr,
+		const struct sockaddr_in6 *netaddr,
+		const struct sockaddr_in6 *netmask)
 {
 	int			i;
 
-	if (IN6_IS_ADDR_V4MAPPED(&addr->in6.sin6_addr))
-	{
-		SockAddr	addr4;
-
-		convSockAddr6to4(addr, &addr4);
-		if (rangeSockAddrAF_INET(&addr4, netaddr, netmask))
-			return 1;
-	}
-
-	if (netaddr->sa.sa_family != AF_INET6 ||
-		netmask->sa.sa_family != AF_INET6)
-		return 0;
-
 	for (i = 0; i < 16; i++)
 	{
-		if (((addr->in6.sin6_addr.s6_addr[i] ^ netaddr->in6.sin6_addr.s6_addr[i]) &
-			 netmask->in6.sin6_addr.s6_addr[i]) != 0)
+		if (((addr->sin6_addr.s6_addr[i] ^ netaddr->sin6_addr.s6_addr[i]) &
+			 netmask->sin6_addr.s6_addr[i]) != 0)
 			return 0;
 	}
 
 	return 1;
 }
+#endif
 
-static void
-convSockAddr6to4(const SockAddr *src, SockAddr *dst)
-{
-	MemSet(dst, 0, sizeof(*dst));
-	dst->in.sin_family = AF_INET;
-	/* both src and dst are assumed to be in network byte order */
-	dst->in.sin_port = src->in6.sin6_port;
-	memcpy(&dst->in.sin_addr.s_addr,
-		   ((char *) (&src->in6.sin6_addr.s6_addr)) + 12,
-		   sizeof(struct in_addr));
-}
 
-#endif /* HAVE_IPV6 */
diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample
index 1116debbc1acf07c85aae9a6c87401cac1a460ae..52c0bd4d73da038660afdbede9555dbaac0f0382 100644
--- a/src/backend/libpq/pg_hba.conf.sample
+++ b/src/backend/libpq/pg_hba.conf.sample
@@ -46,4 +46,6 @@
 
 local   all         all                                                                trust
 host    all         all         127.0.0.1         255.255.255.255                      trust
-host    all         all         ::1               ffff:ffff:ffff:ffff:ffff:ffff        trust
+host    all         all         ::1               ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff        trust
+host    all         all         ::ffff:127.0.0.1/128	trust
+
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index ea4ff64468643774728f103f61fd14b07ed4be50..2cd2c9223f71f40ec997f21427165d88034da74d 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -30,7 +30,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.156 2003/06/09 17:59:19 tgl Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.157 2003/06/12 07:36:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -199,33 +199,30 @@ StreamDoUnlink(void)
 
 int
 StreamServerPort(int family, char *hostName, unsigned short portNumber,
-				 char *unixSocketName, int *fdP)
+	 char *unixSocketName, int ListenSocket[], int MaxListen)
 {
 	int			fd,
 				err;
 	int			maxconn;
 	int			one = 1;
 	int			ret;
-	char		portNumberStr[64];
-	char	   *service;
-	struct addrinfo *addrs = NULL;
-	struct addrinfo hint;
-
-#ifdef HAVE_UNIX_SOCKETS
-	Assert(family == AF_UNIX || isAF_INETx(family));
-#else
-	Assert(isAF_INETx(family));
-#endif
+	char			portNumberStr[64];
+	char			*service;
+	struct addrinfo		*addrs = NULL, *addr;
+	struct addrinfo		hint;
+	int			listen_index = 0;
+	int			added = 0;
 
 	/* Initialize hint structure */
 	MemSet(&hint, 0, sizeof(hint));
 	hint.ai_family = family;
-	hint.ai_flags = AI_PASSIVE;
+	hint.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
 	hint.ai_socktype = SOCK_STREAM;
 
 #ifdef HAVE_UNIX_SOCKETS
 	if (family == AF_UNIX)
 	{
+		/* Lock_AF_UNIX will also fill in sock_path. */
 		if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK)
 			return STATUS_ERROR;
 		service = sock_path;
@@ -246,73 +243,132 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
 		return STATUS_ERROR;
 	}
 
-	if ((fd = socket(family, SOCK_STREAM, 0)) < 0)
+	for (addr = addrs; addr; addr = addr->ai_next)
 	{
-		elog(LOG, "server socket failure: socket(): %s",
-			 strerror(errno));
-		freeaddrinfo2(hint.ai_family, addrs);
-		return STATUS_ERROR;
-	}
+		if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr->ai_family))
+		{
+			/* Only set up a unix domain socket when
+			 * they really asked for it.  The service/port
+			 * is different in that case. */
+			continue;
+		}
 
-	if (isAF_INETx(family))
-	{
-		if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
-						sizeof(one))) == -1)
+		/* See if there is still room to add 1 more socket. */
+		for (; listen_index < MaxListen; listen_index++)
+		{
+			if (ListenSocket[listen_index] == -1)
+			{
+				break;
+			}
+		}
+		if (listen_index == MaxListen)
+		{
+			/* Nothing found. */
+			break;
+		}
+		if ((fd = socket(addr->ai_family, addr->ai_socktype,
+			addr->ai_protocol)) < 0)
 		{
-			elog(LOG, "server socket failure: setsockopt(SO_REUSEADDR): %s",
+			elog(LOG, "server socket failure: socket(): %s",
 				 strerror(errno));
-			freeaddrinfo2(hint.ai_family, addrs);
-			return STATUS_ERROR;
+			continue;
 		}
-	}
 
-	Assert(addrs->ai_next == NULL && addrs->ai_family == family);
-	err = bind(fd, addrs->ai_addr, addrs->ai_addrlen);
-	if (err < 0)
-	{
-		elog(LOG, "server socket failure: bind(): %s\n"
-			 "\tIs another postmaster already running on port %d?",
-			 strerror(errno), (int) portNumber);
-		if (family == AF_UNIX)
-			elog(LOG, "\tIf not, remove socket node (%s) and retry.",
-				 sock_path);
-		else
-			elog(LOG, "\tIf not, wait a few seconds and retry.");
-		freeaddrinfo2(hint.ai_family, addrs);
-		return STATUS_ERROR;
-	}
+
+
+		if (!IS_AF_UNIX(addr->ai_family))
+		{
+			if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+				(char *) &one, sizeof(one))) == -1)
+			{
+				elog(LOG, "server socket failure: "
+					"setsockopt(SO_REUSEADDR): %s",
+					strerror(errno));
+				closesocket(fd);
+				continue;
+			}
+		}
+
+#ifdef IPV6_V6ONLY
+		if (addr->ai_family == AF_INET6)
+		{
+			if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
+				(char *)&one, sizeof(one)) == -1)
+			{
+				elog(LOG, "server socket failure: "
+					"setsockopt(IPV6_V6ONLY): %s",
+					strerror(errno));
+				closesocket(fd);
+				continue;
+			}
+		}
+#endif
+
+		/*
+		 * Note: This might fail on some OS's, like Linux
+		 * older than 2.4.21-pre3, that don't have the IPV6_V6ONLY
+		 * socket option, and map ipv4 addresses to ipv6.  It will
+		 * show ::ffff:ipv4 for all ipv4 connections.
+		 */
+		err = bind(fd, addr->ai_addr, addr->ai_addrlen);
+		if (err < 0)
+		{
+			elog(LOG, "server socket failure: bind(): %s\n"
+				"\tIs another postmaster already running on "
+				"port %d?", strerror(errno), (int) portNumber);
+			if (addr->ai_family == AF_UNIX)
+			{
+				elog(LOG, "\tIf not, remove socket node (%s) "
+					"and retry.", sock_path);
+			}
+			else
+			{
+				elog(LOG, "\tIf not, wait a few seconds and "
+					"retry.");
+			}
+			closesocket(fd);
+			continue;
+		}
 
 #ifdef HAVE_UNIX_SOCKETS
-	if (family == AF_UNIX)
-	{
-		if (Setup_AF_UNIX() != STATUS_OK)
+		if (addr->ai_family == AF_UNIX)
 		{
-			freeaddrinfo2(hint.ai_family, addrs);
-			return STATUS_ERROR;
+			if (Setup_AF_UNIX() != STATUS_OK)
+			{
+				closesocket(fd);
+				break;
+			}
 		}
-	}
 #endif
 
-	/*
-	 * Select appropriate accept-queue length limit.  PG_SOMAXCONN is only
-	 * intended to provide a clamp on the request on platforms where an
-	 * overly large request provokes a kernel error (are there any?).
-	 */
-	maxconn = MaxBackends * 2;
-	if (maxconn > PG_SOMAXCONN)
-		maxconn = PG_SOMAXCONN;
+		/*
+		 * Select appropriate accept-queue length limit.  PG_SOMAXCONN
+		 * is only intended to provide a clamp on the request on
+		 * platforms where an overly large request provokes a kernel
+		 * error (are there any?).
+		 */
+		maxconn = MaxBackends * 2;
+		if (maxconn > PG_SOMAXCONN)
+			maxconn = PG_SOMAXCONN;
+
+		err = listen(fd, maxconn);
+		if (err < 0)
+		{
+			elog(LOG, "server socket failure: listen(): %s",
+				 strerror(errno));
+			closesocket(fd);
+			continue;
+		}
+		ListenSocket[listen_index] = fd;
+		added++;
+	}
 
-	err = listen(fd, maxconn);
-	if (err < 0)
+	freeaddrinfo(addrs);
+
+	if (!added)
 	{
-		elog(LOG, "server socket failure: listen(): %s",
-			 strerror(errno));
-		freeaddrinfo2(hint.ai_family, addrs);
 		return STATUS_ERROR;
 	}
-
-	*fdP = fd;
-	freeaddrinfo2(hint.ai_family, addrs);
 	return STATUS_OK;
 }
 
@@ -325,10 +381,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
 static int
 Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
 {
-	SockAddr	saddr;	/* just used to get socket path */
-
-	UNIXSOCK_PATH(saddr.un, portNumber, unixSocketName);
-	strcpy(sock_path, saddr.un.sun_path);
+	UNIXSOCK_PATH(sock_path, portNumber, unixSocketName);
 
 	/*
 	 * Grab an interlock file associated with the socket file.
@@ -422,13 +475,11 @@ Setup_AF_UNIX(void)
 int
 StreamConnection(int server_fd, Port *port)
 {
-	ACCEPT_TYPE_ARG3 addrlen;
-
 	/* accept connection (and fill in the client (remote) address) */
-	addrlen = sizeof(port->raddr);
+	port->raddr.salen = sizeof(port->raddr.addr);
 	if ((port->sock = accept(server_fd,
-							 (struct sockaddr *) &port->raddr,
-							 &addrlen)) < 0)
+			 (struct sockaddr *) &port->raddr.addr,
+			 &port->raddr.salen)) < 0)
 	{
 		elog(LOG, "StreamConnection: accept() failed: %m");
 		return STATUS_ERROR;
@@ -444,25 +495,27 @@ StreamConnection(int server_fd, Port *port)
 #endif
 
 	/* fill in the server (local) address */
-	addrlen = sizeof(port->laddr);
-	if (getsockname(port->sock, (struct sockaddr *) & port->laddr,
-					&addrlen) < 0)
+	port->laddr.salen = sizeof(port->laddr.addr);
+	if (getsockname(port->sock, (struct sockaddr *) & port->laddr.addr,
+					&port->laddr.salen) < 0)
 	{
 		elog(LOG, "StreamConnection: getsockname() failed: %m");
 		return STATUS_ERROR;
 	}
 
 	/* select NODELAY and KEEPALIVE options if it's a TCP connection */
-	if (isAF_INETx(port->laddr.sa.sa_family))
+	if (!IS_AF_UNIX(port->laddr.addr.ss_family))
 	{
 		int			on = 1;
 
+#ifdef	TCP_NODELAY
 		if (setsockopt(port->sock, IPPROTO_TCP, TCP_NODELAY,
 					   (char *) &on, sizeof(on)) < 0)
 		{
 			elog(LOG, "StreamConnection: setsockopt(TCP_NODELAY) failed: %m");
 			return STATUS_ERROR;
 		}
+#endif
 		if (setsockopt(port->sock, SOL_SOCKET, SO_KEEPALIVE,
 					   (char *) &on, sizeof(on)) < 0)
 		{
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 2b8708fc5d2e326f064a547f744209d58ecbc42c..a0495fff8551872d2fcf03eda41e79777f70c9aa 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -13,7 +13,7 @@
  *
  *	Copyright (c) 2001-2003, PostgreSQL Global Development Group
  *
- *	$Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.36 2003/05/15 16:35:29 momjian Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.37 2003/06/12 07:36:51 momjian Exp $
  * ----------
  */
 #include "postgres.h"
@@ -22,7 +22,9 @@
 #include <fcntl.h>
 #include <sys/param.h>
 #include <sys/time.h>
+#include <sys/types.h>
 #include <sys/socket.h>
+#include <netdb.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <errno.h>
@@ -36,6 +38,7 @@
 #include "catalog/pg_shadow.h"
 #include "catalog/pg_database.h"
 #include "libpq/pqsignal.h"
+#include "libpq/libpq.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
 #include "utils/memutils.h"
@@ -69,7 +72,7 @@ bool		pgstat_is_running = false;
  */
 static int	pgStatSock = -1;
 static int	pgStatPipe[2];
-static struct sockaddr_in pgStatAddr;
+static struct sockaddr_storage pgStatAddr;
 static int	pgStatPmPipe[2] = {-1, -1};
 
 static int	pgStatPid;
@@ -141,7 +144,9 @@ static void pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len);
 void
 pgstat_init(void)
 {
-	int			alen;
+	ACCEPT_TYPE_ARG3	alen;
+	struct	addrinfo	*addr, hints;
+	int			ret;
 
 	/*
 	 * Force start of collector daemon if something to collect
@@ -174,7 +179,24 @@ pgstat_init(void)
 	/*
 	 * Create the UDP socket for sending and receiving statistic messages
 	 */
-	if ((pgStatSock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
+	hints.ai_flags = AI_PASSIVE;
+	hints.ai_family = PF_UNSPEC;
+	hints.ai_socktype = SOCK_DGRAM;
+	hints.ai_protocol = 0;
+	hints.ai_addrlen = 0;
+	hints.ai_addr = NULL;
+	hints.ai_canonname = NULL;
+	hints.ai_next = NULL;
+	ret = getaddrinfo2("localhost", NULL, &hints, &addr);
+	if (ret || !addr)
+	{
+		elog(LOG, "PGSTAT: getaddrinfo2() failed: %s",
+			gai_strerror(ret));
+		goto startup_failed;
+	}
+	
+	if ((pgStatSock = socket(addr->ai_family,
+		addr->ai_socktype, addr->ai_protocol)) < 0)
 	{
 		elog(LOG, "PGSTAT: socket() failed: %m");
 		goto startup_failed;
@@ -184,16 +206,16 @@ pgstat_init(void)
 	 * Bind it to a kernel assigned port on localhost and get the assigned
 	 * port via getsockname().
 	 */
-	pgStatAddr.sin_family = AF_INET;
-	pgStatAddr.sin_port = htons(0);
-	inet_aton("127.0.0.1", &(pgStatAddr.sin_addr));
-	alen = sizeof(pgStatAddr);
-	if (bind(pgStatSock, (struct sockaddr *) & pgStatAddr, alen) < 0)
+	if (bind(pgStatSock, addr->ai_addr, addr->ai_addrlen) < 0)
 	{
-		elog(LOG, "PGSTAT: bind(127.0.0.1) failed: %m");
+		elog(LOG, "PGSTAT: bind() failed: %m");
 		goto startup_failed;
 	}
-	if (getsockname(pgStatSock, (struct sockaddr *) & pgStatAddr, &alen) < 0)
+	freeaddrinfo2(hints.ai_family, addr);
+	addr = NULL;
+
+	alen = sizeof(pgStatAddr);
+	if (getsockname(pgStatSock, (struct sockaddr *)&pgStatAddr, &alen) < 0)
 	{
 		elog(LOG, "PGSTAT: getsockname() failed: %m");
 		goto startup_failed;
@@ -235,6 +257,11 @@ pgstat_init(void)
 	return;
 
 startup_failed:
+	if (addr)
+	{
+		freeaddrinfo2(hints.ai_family, addr);
+	}
+
 	if (pgStatSock >= 0)
 		closesocket(pgStatSock);
 	pgStatSock = -1;
@@ -1496,7 +1523,7 @@ pgstat_recvbuffer(void)
 	int			msg_send = 0;	/* next send index in buffer */
 	int			msg_recv = 0;	/* next receive index */
 	int			msg_have = 0;	/* number of bytes stored */
-	struct sockaddr_in fromaddr;
+	struct sockaddr_storage	fromaddr;
 	int			fromlen;
 	bool		overflow = false;
 
@@ -1601,9 +1628,9 @@ pgstat_recvbuffer(void)
 		if (FD_ISSET(pgStatSock, &rfds))
 		{
 			fromlen = sizeof(fromaddr);
-			len = recvfrom(pgStatSock,
-						   (char *) &input_buffer, sizeof(PgStat_Msg), 0,
-						   (struct sockaddr *) &fromaddr, &fromlen);
+			len = recvfrom(pgStatSock, (char *) &input_buffer,
+				sizeof(PgStat_Msg), 0,
+				(struct sockaddr *) &fromaddr, &fromlen);
 			if (len < 0)
 			{
 				elog(LOG, "PGSTATBUFF: recvfrom() failed: %m");
@@ -1629,9 +1656,7 @@ pgstat_recvbuffer(void)
 			 * kernel-level check due to having used connect(), but let's
 			 * do it anyway.)
 			 */
-			if (fromaddr.sin_addr.s_addr != pgStatAddr.sin_addr.s_addr)
-				continue;
-			if (fromaddr.sin_port != pgStatAddr.sin_port)
+			if (memcmp(&fromaddr, &pgStatAddr, fromlen))
 				continue;
 
 			/*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 5b16d06a994bf2ea449bc0c478191cff170a23b2..e32a668bc715cd0211683bf8de5a24befdba2f4e 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.332 2003/06/11 06:56:06 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.333 2003/06/12 07:36:51 momjian Exp $
  *
  * NOTES
  *
@@ -168,14 +168,9 @@ int			ReservedBackends;
 
 static char *progname = (char *) NULL;
 
-/*
- * Default Values
- */
-static int	ServerSock_INET = INVALID_SOCK;		/* stream socket server */
-
-#ifdef HAVE_UNIX_SOCKETS
-static int	ServerSock_UNIX = INVALID_SOCK;		/* stream socket server */
-#endif
+/* The sockets we're listening to. */
+#define	MAXLISTEN	10
+int	ListenSocket[MAXLISTEN];
 
 /* Used to reduce macros tests */
 #ifdef EXEC_BACKEND
@@ -384,10 +379,11 @@ reg_reply(DNSServiceRegistrationReplyErrorType errorCode, void *context)
 int
 PostmasterMain(int argc, char *argv[])
 {
-	int			opt;
-	int			status;
+	int		opt;
+	int		status;
 	char		original_extraoptions[MAXPGPATH];
-	char	   *potential_DataDir = NULL;
+	char		*potential_DataDir = NULL;
+	int		i;
 
 	*original_extraoptions = '\0';
 
@@ -713,32 +709,53 @@ PostmasterMain(int argc, char *argv[])
 	/*
 	 * Establish input sockets.
 	 */
+	for (i = 0; i < MAXLISTEN; i++)
+	{
+		ListenSocket[i] = -1;
+	}
 	if (NetServer)
 	{
-#ifdef HAVE_IPV6
-		/* Try INET6 first.  May fail if kernel doesn't support IP6 */
-		status = StreamServerPort(AF_INET6, VirtualHost,
-								  (unsigned short) PostPortNumber,
-								  UnixSocketDir,
-								  &ServerSock_INET);
-		if (status != STATUS_OK)
+		if (VirtualHost && VirtualHost[0])
 		{
-			elog(LOG, "IPv6 support disabled --- perhaps the kernel does not support IPv6");
-#endif
-			status = StreamServerPort(AF_INET, VirtualHost,
-									  (unsigned short) PostPortNumber,
-									  UnixSocketDir,
-									  &ServerSock_INET);
+			char	*p, *q;
+			char	c = 0;
+
+			q = VirtualHost;
+			do
+			{
+				p = strchr(q, ' ');
+				if (p)
+				{
+					c = *p;
+					*p = '\0';
+				}
+				status = StreamServerPort(AF_UNSPEC, q,
+					(unsigned short) PostPortNumber,
+					UnixSocketDir, ListenSocket, MAXLISTEN);
+				if (status != STATUS_OK)
+				{
+					postmaster_error("cannot create tcpip "
+						"listen socket for: %s", p);
+				}
+				if (p)
+				{
+					*p = c;
+					q = p + 1;
+				}
+			}
+			while (p);
+		}
+		else
+		{
+			status = StreamServerPort(AF_UNSPEC, NULL,
+				(unsigned short) PostPortNumber,
+				UnixSocketDir, ListenSocket, MAXLISTEN);
 			if (status != STATUS_OK)
 			{
-				postmaster_error("cannot create INET stream port");
-				ExitPostmaster(1);
+				postmaster_error("cannot create tcpip listen "
+					"socket.");
 			}
-#ifdef HAVE_IPV6
-			else
-				elog(LOG, "IPv4 socket created");
 		}
-#endif
 #ifdef USE_RENDEZVOUS                    
                 if (service_name != NULL)
                 {
@@ -754,10 +771,9 @@ PostmasterMain(int argc, char *argv[])
 	}
 
 #ifdef HAVE_UNIX_SOCKETS
-	status = StreamServerPort(AF_UNIX, VirtualHost,
-							  (unsigned short) PostPortNumber,
-							  UnixSocketDir,
-							  &ServerSock_UNIX);
+	status = StreamServerPort(AF_UNIX, NULL,
+			(unsigned short) PostPortNumber,
+			UnixSocketDir, ListenSocket, MAXLISTEN);
 	if (status != STATUS_OK)
 	{
 		postmaster_error("cannot create UNIX stream port");
@@ -961,12 +977,11 @@ usage(const char *progname)
 static int
 ServerLoop(void)
 {
-	fd_set		readmask,
-				writemask;
+	fd_set			readmask, writemask;
 	int			nSockets;
-	struct timeval now,
-				later;
-	struct timezone tz;
+	struct timeval		now, later;
+	struct timezone		tz;
+	int			i;
 
 	gettimeofday(&now, &tz);
 
@@ -1065,40 +1080,22 @@ ServerLoop(void)
 		 * New connection pending on our well-known port's socket? If so,
 		 * fork a child process to deal with it.
 		 */
-
-#ifdef HAVE_UNIX_SOCKETS
-		if (ServerSock_UNIX != INVALID_SOCK
-			&& FD_ISSET(ServerSock_UNIX, &rmask))
+		for (i = 0; i < MAXLISTEN; i++)
 		{
-			port = ConnCreate(ServerSock_UNIX);
-			if (port)
+			if (ListenSocket[i] != -1 && FD_ISSET(ListenSocket[i], &rmask))
 			{
-				BackendStartup(port);
-
-				/*
-				 * We no longer need the open socket or port structure in
-				 * this process
-				 */
-				StreamClose(port->sock);
-				ConnFree(port);
-			}
-		}
-#endif
-
-		if (ServerSock_INET != INVALID_SOCK
-			&& FD_ISSET(ServerSock_INET, &rmask))
-		{
-			port = ConnCreate(ServerSock_INET);
-			if (port)
-			{
-				BackendStartup(port);
-
-				/*
-				 * We no longer need the open socket or port structure in
-				 * this process
-				 */
-				StreamClose(port->sock);
-				ConnFree(port);
+				port = ConnCreate(ListenSocket[i]);
+				if (port)
+				{
+					BackendStartup(port);
+
+					/*
+					 * We no longer need the open socket
+					 * or port structure in this process
+					 */
+					StreamClose(port->sock);
+					ConnFree(port);
+				}
 			}
 		}
 
@@ -1118,25 +1115,20 @@ static int
 initMasks(fd_set *rmask, fd_set *wmask)
 {
 	int			nsocks = -1;
+	int			i;
 
 	FD_ZERO(rmask);
 	FD_ZERO(wmask);
 
-#ifdef HAVE_UNIX_SOCKETS
-	if (ServerSock_UNIX != INVALID_SOCK)
+	for (i = 0; i < MAXLISTEN; i++)
 	{
-		FD_SET(ServerSock_UNIX, rmask);
-
-		if (ServerSock_UNIX > nsocks)
-			nsocks = ServerSock_UNIX;
-	}
-#endif
-
-	if (ServerSock_INET != INVALID_SOCK)
-	{
-		FD_SET(ServerSock_INET, rmask);
-		if (ServerSock_INET > nsocks)
-			nsocks = ServerSock_INET;
+		int	fd = ListenSocket[i];
+		if (fd != -1)
+		{
+			FD_SET(fd, rmask);
+			if (fd > nsocks)
+				nsocks = fd;
+		}
 	}
 
 	return nsocks + 1;
@@ -1220,7 +1212,7 @@ ProcessStartupPacket(Port *port, bool SSLdone)
 
 #ifdef USE_SSL
 		/* No SSL when disabled or on Unix sockets */
-		if (!EnableSSL || port->laddr.sa.sa_family != AF_INET)
+		if (!EnableSSL || port->laddr.addr.ss_family != AF_INET)
 			SSLok = 'N';
 		else
 			SSLok = 'S';		/* Support for SSL */
@@ -1560,14 +1552,18 @@ ConnFree(Port *conn)
 void
 ClosePostmasterPorts(bool pgstat_too)
 {
+	int	i;
+
 	/* Close the listen sockets */
-	if (NetServer)
-		StreamClose(ServerSock_INET);
-	ServerSock_INET = INVALID_SOCK;
-#ifdef HAVE_UNIX_SOCKETS
-	StreamClose(ServerSock_UNIX);
-	ServerSock_UNIX = INVALID_SOCK;
-#endif
+	for (i = 0; i < MAXLISTEN; i++)
+	{
+		if (ListenSocket[i] != -1)
+		{
+			StreamClose(ListenSocket[i]);
+			ListenSocket[i] = -1;
+		}
+	}
+
 	/* Close pgstat control sockets, unless we're starting pgstat itself */
 	if (pgstat_too)
 		pgstat_close_sockets();
@@ -2226,19 +2222,20 @@ split_opts(char **argv, int *argcp, char *s)
 static int
 BackendFork(Port *port)
 {
-	char	   *remote_host;
-	char	  **av;
-	int			maxac;
-	int			ac;
+	char		**av;
+	int		maxac;
+	int		ac;
 	char		debugbuf[32];
 	char		protobuf[32];
 #ifdef EXEC_BACKEND
 	char		pbuf[NAMEDATALEN + 256];
 #endif
-	int			i;
-	int			status;
-	struct timeval now;
-	struct timezone tz;
+	int		i;
+	int		status;
+	struct timeval	now;
+	struct timezone	tz;
+	char		remote_host[NI_MAXHOST];
+	char		remote_port[NI_MAXSERV];
 
 	/*
 	 * Let's clean up ourselves as the postmaster child
@@ -2286,63 +2283,37 @@ BackendFork(Port *port)
 	/*
 	 * Get the remote host name and port for logging and status display.
 	 */
-	if (isAF_INETx(port->raddr.sa.sa_family))
+	remote_host[0] = '\0';
+	remote_port[0] = '\0';
+	if (!getnameinfo((struct sockaddr *)&port->raddr.addr,
+		port->raddr.salen,
+		remote_host, sizeof(remote_host),
+		remote_port, sizeof(remote_host),
+		(log_hostname ? 0 : NI_NUMERICHOST) | NI_NUMERICSERV))
 	{
-		unsigned short remote_port;
-		char	   *host_addr;
-#ifdef HAVE_IPV6
-		char	   ip_hostinfo[INET6_ADDRSTRLEN];
-#else
-		char	   ip_hostinfo[INET_ADDRSTRLEN];
-#endif
-
-		remote_port = ntohs(port->raddr.in.sin_port);
-		host_addr = SockAddr_ntop(&port->raddr, ip_hostinfo,
-			sizeof(ip_hostinfo), 1);
-
-		remote_host = NULL;
-
-		if (log_hostname)
-		{
-			struct hostent *host_ent;
-
-			host_ent = gethostbyaddr((char *) &port->raddr.in.sin_addr,
-									 sizeof(port->raddr.in.sin_addr),
-									 AF_INET);
-
-			if (host_ent)
-			{
-				remote_host = palloc(strlen(host_addr) + strlen(host_ent->h_name) + 3);
-				sprintf(remote_host, "%s[%s]", host_ent->h_name, host_addr);
-			}
-		}
-
-		if (remote_host == NULL)
-			remote_host = pstrdup(host_addr);
-
-		if (Log_connections)
-			elog(LOG, "connection received: host=%s port=%hu",
-				 remote_host, remote_port);
-
-		if (LogSourcePort)
-		{
-			/* modify remote_host for use in ps status */
-			int			slen = strlen(remote_host) + 10;
-			char	   *str = palloc(slen);
-
-			snprintf(str, slen, "%s:%hu", remote_host, remote_port);
-			pfree(remote_host);
-			remote_host = str;
-		}
+		getnameinfo((struct sockaddr *)&port->raddr.addr,
+			port->raddr.salen,
+			remote_host, sizeof(remote_host),
+			remote_port, sizeof(remote_host),
+			NI_NUMERICHOST | NI_NUMERICSERV);
 	}
-	else
+
+	if (Log_connections)
 	{
-	   	/* not AF_INET */
-		remote_host = "[local]";
+		elog(LOG, "connection received: host=%s port=%s",
+			remote_host, remote_port);
+	}
 
-		if (Log_connections)
-			elog(LOG, "connection received: host=%s",
-				 remote_host);
+	if (LogSourcePort)
+	{
+		/* modify remote_host for use in ps status */
+		int		slen = strlen(remote_host) + 10;
+		char		*str = palloc(slen);
+
+		snprintf(str, slen, "%s:%s", remote_host, remote_port);
+		strncpy(remote_host, str, sizeof(remote_host));
+		remote_host[sizeof(remote_host) - 1] = '\0';
+		pfree(str);
 	}
 
 	/*
@@ -2516,14 +2487,8 @@ ExitPostmaster(int status)
 	 *
 	 * MUST		-- vadim 05-10-1999
 	 */
-	if (ServerSock_INET != INVALID_SOCK)
-		StreamClose(ServerSock_INET);
-	ServerSock_INET = INVALID_SOCK;
-#ifdef HAVE_UNIX_SOCKETS
-	if (ServerSock_UNIX != INVALID_SOCK)
-		StreamClose(ServerSock_UNIX);
-	ServerSock_UNIX = INVALID_SOCK;
-#endif
+	/* Should I use true instead? */
+	ClosePostmasterPorts(false);
 
 	proc_exit(status);
 }
diff --git a/src/include/getaddrinfo.h b/src/include/getaddrinfo.h
index 2b47d613e9967f067f8b83fdddaaccbaee52b905..416dc65fb1ef6bf2cabf9e2f31fba0e1ad79ad94 100644
--- a/src/include/getaddrinfo.h
+++ b/src/include/getaddrinfo.h
@@ -16,7 +16,7 @@
  *
  * Copyright (c) 2003, PostgreSQL Global Development Group
  *
- * $Id: getaddrinfo.h,v 1.2 2003/04/02 00:49:28 tgl Exp $
+ * $Id: getaddrinfo.h,v 1.3 2003/06/12 07:36:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,23 +40,30 @@ struct addrinfo {
 	struct addrinfo *ai_next;
 };
 
-#define EAI_BADFLAGS	-1
+#define EAI_BADFLAGS		-1
 #define EAI_NONAME		-2
 #define EAI_AGAIN		-3
 #define EAI_FAIL		-4
-#define EAI_NODATA		-5
 #define EAI_FAMILY		-6
-#define EAI_SOCKTYPE	-7
+#define EAI_SOCKTYPE		-7
 #define EAI_SERVICE		-8
-#define EAI_ADDRFAMILY	-9
 #define EAI_MEMORY		-10
 #define EAI_SYSTEM		-11
 
 #define AI_PASSIVE		0x0001
 #define AI_NUMERICHOST	0x0004
 
+#define NI_NUMERICHOST	1
+#define NI_NUMERICSERV	2
+
 #endif /* HAVE_STRUCT_ADDRINFO */
 
+#ifndef	NI_MAXHOST
+#define NI_MAXHOST	1025
+#define NI_MAXSERV	32
+#endif
+
+
 
 #ifndef HAVE_GETADDRINFO
 
@@ -76,10 +83,18 @@ struct addrinfo {
 #endif
 #define gai_strerror pg_gai_strerror
 
+#ifdef getnameinfo
+#undef getnameinfo
+#endif
+#define	getnameinfo pg_getnameinfo
+
 extern int getaddrinfo(const char *node, const char *service,
 					   const struct addrinfo *hints, struct addrinfo **res);
 extern void freeaddrinfo(struct addrinfo *res);
 extern const char *gai_strerror(int errcode);
+extern int getnameinfo(const struct sockaddr *sa, int salen,
+			char *node, int nodelen,
+			char *service, int servicelen, int flags);
 
 #endif /* HAVE_GETADDRINFO */
 
diff --git a/src/include/libpq/ip.h b/src/include/libpq/ip.h
index b43d9972663b555584c0eebfb96e86eedbd45e57..b770d33bfe391274d0c74614811b12f5bd8f8228 100644
--- a/src/include/libpq/ip.h
+++ b/src/include/libpq/ip.h
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 2003, PostgreSQL Global Development Group
  *
- * $Id: ip.h,v 1.7 2003/06/12 07:00:57 momjian Exp $
+ * $Id: ip.h,v 1.8 2003/06/12 07:36:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,12 +21,17 @@ extern int   getaddrinfo2(const char *hostname, const char *servname,
 						  struct addrinfo **result);
 extern void  freeaddrinfo2(int hint_ai_family, struct addrinfo *ai);
 
-extern char *SockAddr_ntop(const SockAddr *sa, char *dst, size_t cnt,
-						   int v4conv);
-extern int   SockAddr_pton(SockAddr *sa, const char *src);
+extern int   rangeSockAddr(const struct sockaddr_storage *addr,
+			const struct sockaddr_storage *netaddr,
+			const struct sockaddr_storage *netmask);
 
-extern int   isAF_INETx(const int family);
-extern int   rangeSockAddr(const SockAddr *addr, const SockAddr *netaddr,
-						   const SockAddr *netmask);
+extern int SockAddr_cidr_mask(struct sockaddr_storage **mask,
+				char *numbits, int family);
+
+#ifdef	HAVE_UNIX_SOCKETS
+#define	IS_AF_UNIX(fam)	(fam == AF_UNIX)
+#else
+#define	IS_AF_UNIX(fam) (0)
+#endif
 
 #endif /* IP_H */
diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h
index cbe0b646e74e3092fcfa6836c9e27f76d9ae262d..9f72b7e432c042137129f4fa596868f4d213309d 100644
--- a/src/include/libpq/libpq.h
+++ b/src/include/libpq/libpq.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq.h,v 1.57 2003/04/19 00:02:29 tgl Exp $
+ * $Id: libpq.h,v 1.58 2003/06/12 07:36:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,7 +46,8 @@ typedef struct
  * prototypes for functions in pqcomm.c
  */
 extern int StreamServerPort(int family, char *hostName,
-			  unsigned short portNumber, char *unixSocketName, int *fdP);
+	unsigned short portNumber, char *unixSocketName, int ListenSocket[],
+	int MaxListen);
 extern int	StreamConnection(int server_fd, Port *port);
 extern void StreamClose(int sock);
 extern void TouchSocketFile(void);
diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h
index eac9867391b3e7d4391c876c378da322dc0ad09c..ed41464c2ccee0156281d83dd92a9ddaa300db6f 100644
--- a/src/include/libpq/pqcomm.h
+++ b/src/include/libpq/pqcomm.h
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pqcomm.h,v 1.85 2003/05/08 18:33:32 tgl Exp $
+ * $Id: pqcomm.h,v 1.86 2003/06/12 07:36:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,58 +32,60 @@
 #include <netinet/in.h>
 #endif   /* not WIN32 */
 
+#ifndef	HAVE_STRUCT_SOCKADDR_STORAGE
+/* Define a struct sockaddr_storage if we don't have one. */
+/*
+ * Desired design of maximum size and alignment
+ */
+#define _SS_MAXSIZE    128  /* Implementation specific max size */
+#define _SS_ALIGNSIZE  (sizeof (int64_t))
+                         /* Implementation specific desired alignment */
+/*
+ * Definitions used for sockaddr_storage structure paddings design.
+ */
+#define	_SS_PAD1SIZE	(_SS_ALIGNSIZE - sizeof (sa_family_t))
+#define	_SS_PAD2SIZE	(_SS_MAXSIZE - (sizeof (sa_family_t) + \
+				_SS_PAD1SIZE + _SS_ALIGNSIZE))
 
-#ifndef INET_ADDRSTRLEN
-#define INET_ADDRSTRLEN 16
-#endif
-
-#ifndef INET6_ADDRSTRLEN
-#define INET6_ADDRSTRLEN 46
+struct sockaddr_storage {
+#ifdef SALEN
+    uint8_t	__ss_len;        /* address length */
 #endif
-
-
-#ifndef HAVE_STRUCT_SOCKADDR_UN
-struct sockaddr_un
-{
-	short int	sun_family;		/* AF_UNIX */
-	char		sun_path[108];	/* path name (gag) */
+    sa_family_t	ss_family;	/* address family */
+
+    char	__ss_pad1[_SS_PAD1SIZE];
+		/* 6 byte pad, this is to make implementation
+		 * specific pad up to alignment field that
+		 * follows explicit in the data structure */
+    int64_t	__ss_align;
+		/* field to force desired structure
+		 * storage alignment */
+    char	__ss_pad2[_SS_PAD2SIZE];
+		/* 112 byte pad to achieve desired size,
+		 * _SS_MAXSIZE value minus size of ss_family
+		 * __ss_pad1, __ss_align fields is 112 */
 };
 #endif
 
-/* Define a generic socket address type. */
-
-typedef union SockAddr
-{
-	struct sockaddr sa;
-	struct sockaddr_in in;
-#ifdef HAVE_IPV6
-	struct sockaddr_in6 in6;
-#endif
-	struct sockaddr_un un;
+typedef struct {
+	struct sockaddr_storage	addr;
+	ACCEPT_TYPE_ARG3	salen;
 } SockAddr;
 
+/* Some systems don't have it, so default it to 0 so it doesn't
+ * have any effect on those systems. */
+#ifndef	AI_ADDRCONFIG
+#define	AI_ADDRCONFIG 0
+#endif
 
 /* Configure the UNIX socket location for the well known port. */
 
-#define UNIXSOCK_PATH(sun,port,defpath) \
-		snprintf((sun).sun_path, sizeof((sun).sun_path), "%s/.s.PGSQL.%d", \
+#define UNIXSOCK_PATH(path,port,defpath) \
+		snprintf(path, sizeof(path), "%s/.s.PGSQL.%d", \
 				((defpath) && *(defpath) != '\0') ? (defpath) : \
 				DEFAULT_PGSOCKET_DIR, \
 				(port))
 
-/*
- *		We do this because sun_len is in BSD's struct, while others don't.
- *		We never actually set BSD's sun_len, and I can't think of a
- *		platform-safe way of doing it, but the code still works. bjm
- */
-#if defined(SUN_LEN)
-#define UNIXSOCK_LEN(sun) \
-		(SUN_LEN(&(sun)))
-#else
-#define UNIXSOCK_LEN(sun) \
-		(strlen((sun).sun_path) + offsetof(struct sockaddr_un, sun_path))
-#endif
-
 /*
  * These manipulate the frontend/backend protocol version number.
  *
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index b20cecf194876283ae890cae9043842321b05771..a15ca6b6a6f8e0834f5a81a35ed2a9bdf3eb8acb 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -411,6 +411,9 @@
 /* Define to 1 if the system has the type `struct fcred'. */
 #undef HAVE_STRUCT_FCRED
 
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
+
 /* Define to 1 if the system has the type `struct sockaddr_un'. */
 #undef HAVE_STRUCT_SOCKADDR_UN
 
@@ -487,6 +490,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define to 1 if you have unix sockets. */
+#undef HAVE_UNIX_SOCKETS
+
 /* Define to 1 if you have the `utime' function. */
 #undef HAVE_UTIME
 
diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h
index e8699c2f4a02c0308cfd9e4333a2132dff52224e..3bf316a5805c33059bd80fc57178fad1104c8781 100644
--- a/src/include/pg_config_manual.h
+++ b/src/include/pg_config_manual.h
@@ -6,7 +6,7 @@
  * for developers.  If you edit any of these, be sure to do a *full*
  * rebuild (and an initdb if noted).
  *
- * $Id: pg_config_manual.h,v 1.3 2003/05/15 16:35:29 momjian Exp $
+ * $Id: pg_config_manual.h,v 1.4 2003/06/12 07:36:51 momjian Exp $
  *------------------------------------------------------------------------
  */
 
@@ -127,11 +127,10 @@
 #define BITS_PER_BYTE		8
 
 /*
- * Define this if your operating system supports AF_UNIX family
- * sockets.
+ * Disable UNIX sockets for those operating system.
  */
-#if !defined(__QNX__) && !defined(__BEOS__) && !defined(WIN32)
-# define HAVE_UNIX_SOCKETS 1
+#if defined(__QNX__) || defined(__BEOS__) || defined(WIN32)
+# undef HAVE_UNIX_SOCKETS
 #endif
 
 /*
diff --git a/src/include/port/bsdi.h b/src/include/port/bsdi.h
index e5ba051f239b6168c397e6d0e7638a0013600e57..3a2aa59d096556bd96492f7577fe64ae5d100ae3 100644
--- a/src/include/port/bsdi.h
+++ b/src/include/port/bsdi.h
@@ -9,7 +9,3 @@
 
 typedef unsigned char slock_t;
 
-/* This is marked as obsoleted in BSD/OS 4.3. */
-#ifndef EAI_ADDRFAMILY
-#define  EAI_ADDRFAMILY		1
-#endif
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 64e39c7baf3e6844b36d66e5cba2a7b8b70078de..4445bd217883de6def2feb66d37b0eaeccde324d 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.243 2003/06/09 17:59:19 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.244 2003/06/12 07:36:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -727,6 +727,7 @@ connectMakeNonblocking(PGconn *conn)
 static int
 connectNoDelay(PGconn *conn)
 {
+#ifdef	TCP_NODELAY
 	int			on = 1;
 
 	if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
@@ -738,6 +739,7 @@ connectNoDelay(PGconn *conn)
 						  SOCK_STRERROR(SOCK_ERRNO));
 		return 0;
 	}
+#endif
 
 	return 1;
 }
@@ -751,15 +753,20 @@ connectNoDelay(PGconn *conn)
 static void
 connectFailureMessage(PGconn *conn, int errorno)
 {
-	if (conn->raddr.sa.sa_family == AF_UNIX)
+	char	hostname[NI_MAXHOST];
+	char	service[NI_MAXHOST];
+
+	getnameinfo((struct sockaddr *)&conn->raddr.addr, conn->raddr.salen,
+		hostname, sizeof(hostname), service, sizeof(service),
+		NI_NUMERICHOST | NI_NUMERICSERV);
+	if (conn->raddr.addr.ss_family == AF_UNIX)
 		printfPQExpBuffer(&conn->errorMessage,
 						  libpq_gettext(
 									  "could not connect to server: %s\n"
 						"\tIs the server running locally and accepting\n"
 						  "\tconnections on Unix domain socket \"%s\"?\n"
 										),
-						  SOCK_STRERROR(errorno),
-						  conn->raddr.un.sun_path);
+			SOCK_STRERROR(errorno), service);
 	else
 		printfPQExpBuffer(&conn->errorMessage,
 						  libpq_gettext(
@@ -788,10 +795,10 @@ static int
 connectDBStart(PGconn *conn)
 {
 	int			portnum;
-	char		portstr[64];
-	struct addrinfo *addrs = NULL;
-	struct addrinfo hint;
-	const char *node = NULL;
+	char			portstr[64];
+	struct addrinfo		*addrs = NULL;
+	struct addrinfo		hint;
+	const char		*node = NULL;
 	int			ret;
 
 	if (!conn)
@@ -808,6 +815,7 @@ connectDBStart(PGconn *conn)
 	/* Initialize hint structure */
 	MemSet(&hint, 0, sizeof(hint));
 	hint.ai_socktype = SOCK_STREAM;
+	hint.ai_family = AF_UNSPEC;
 
 	/* Set up port number as a string */
 	if (conn->pgport != NULL && conn->pgport[0] != '\0')
@@ -829,17 +837,15 @@ connectDBStart(PGconn *conn)
 		node = conn->pghost;
 		hint.ai_family = AF_UNSPEC;
 	}
+#ifdef HAVE_UNIX_SOCKETS
 	else
 	{
 		/* pghostaddr and pghost are NULL, so use Unix domain socket */
-#ifdef HAVE_UNIX_SOCKETS
-		node = "unix";
+		node = NULL;
 		hint.ai_family = AF_UNIX;
-		UNIXSOCK_PATH(conn->raddr.un, portnum, conn->pgunixsocket);
-		conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un);
-		StrNCpy(portstr, conn->raddr.un.sun_path, sizeof(portstr));
-#endif   /* HAVE_UNIX_SOCKETS */
+		UNIXSOCK_PATH(portstr, portnum, conn->pgunixsocket);
 	}
+#endif   /* HAVE_UNIX_SOCKETS */
 
 	/* Use getaddrinfo2() to resolve the address */
 	ret = getaddrinfo2(node, portstr, &hint, &addrs);
@@ -1066,12 +1072,11 @@ keep_going:						/* We will come back to here until there
 					/* Remember current address for possible error msg */
 					memcpy(&conn->raddr, addr_cur->ai_addr,
 						   addr_cur->ai_addrlen);
-					conn->raddr_len = addr_cur->ai_addrlen;
 
 					/* Open a socket */
 					conn->sock = socket(addr_cur->ai_family,
-										SOCK_STREAM,
-										addr_cur->ai_protocol);
+							addr_cur->ai_socktype,
+							addr_cur->ai_protocol);
 					if (conn->sock < 0)
 					{
 						/*
@@ -1093,13 +1098,23 @@ keep_going:						/* We will come back to here until there
 					 * Select socket options: no delay of outgoing data for
 					 * TCP sockets, and nonblock mode.  Fail if this fails.
 					 */
-					if (isAF_INETx(addr_cur->ai_family))
+					if (!IS_AF_UNIX(addr_cur->ai_family))
 					{
 						if (!connectNoDelay(conn))
-							break;
+						{
+							closesocket(conn->sock);
+							conn->sock = -1;
+							conn->addr_cur = addr_cur->ai_next;
+							continue;
+						}
 					}
 					if (connectMakeNonblocking(conn) == 0)
-						break;
+					{
+						closesocket(conn->sock);
+						conn->sock = -1;
+						conn->addr_cur = addr_cur->ai_next;
+						continue;
+					}
 					/*
 					 * Start/make connection.  This should not block, since
 					 * we are in nonblock mode.  If it does, well, too bad.
@@ -1163,9 +1178,8 @@ retry_connect:
 
 		case CONNECTION_STARTED:
 			{
-				ACCEPT_TYPE_ARG3 laddrlen;
 				int			optval;
-				ACCEPT_TYPE_ARG3 optlen = sizeof(optval);
+				ACCEPT_TYPE_ARG3	optlen = sizeof(optval);
 
 				/*
 				 * Write ready, since we've made it here, so the
@@ -1212,11 +1226,13 @@ retry_connect:
 				}
 
 				/* Fill in the client address */
-				laddrlen = sizeof(conn->laddr);
-				if (getsockname(conn->sock, &conn->laddr.sa, &laddrlen) < 0)
+				conn->laddr.salen = sizeof(conn->laddr.addr);
+				if (getsockname(conn->sock, 
+					(struct sockaddr *)&conn->laddr.addr,
+					&conn->laddr.salen) < 0)
 				{
 					printfPQExpBuffer(&conn->errorMessage,
-									  libpq_gettext("could not get client address from socket: %s\n"),
+						libpq_gettext("could not get client address from socket: %s\n"),
 									  SOCK_STRERROR(SOCK_ERRNO));
 					goto error_return;
 				}
@@ -1240,7 +1256,7 @@ retry_connect:
 				 */
 
 #ifdef HAVE_UNIX_SOCKETS
-				if (conn->raddr.sa.sa_family == AF_UNIX)
+				if (conn->raddr.addr.ss_family == AF_UNIX)
 				{
 					/* Don't bother requesting SSL over a Unix socket */
 					conn->allow_ssl_try = false;
@@ -2044,14 +2060,15 @@ PQrequestCancel(PGconn *conn)
 	 * We need to open a temporary connection to the postmaster. Use the
 	 * information saved by connectDB to do this with only kernel calls.
 	 */
-	if ((tmpsock = socket(conn->raddr.sa.sa_family, SOCK_STREAM, 0)) < 0)
+	if ((tmpsock = socket(conn->raddr.addr.ss_family, SOCK_STREAM, 0)) < 0)
 	{
 		strcpy(conn->errorMessage.data,
 			   "PQrequestCancel() -- socket() failed: ");
 		goto cancel_errReturn;
 	}
 retry3:
-	if (connect(tmpsock, &conn->raddr.sa, conn->raddr_len) < 0)
+	if (connect(tmpsock, (struct sockaddr *)&conn->raddr.addr,
+		conn->raddr.salen) < 0)
 	{
 		if (SOCK_ERRNO == EINTR)
 			/* Interrupted system call - we'll just try again */
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index f710f58b8e49bf20f6ecd6e7cbb531760aee2332..47dbbb4af5f60e478ae5497444f3693ee0937f2c 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-int.h,v 1.72 2003/06/09 17:59:19 tgl Exp $
+ * $Id: libpq-int.h,v 1.73 2003/06/12 07:36:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -263,7 +263,6 @@ struct pg_conn
 	int			sock;			/* Unix FD for socket, -1 if not connected */
 	SockAddr	laddr;			/* Local address */
 	SockAddr	raddr;			/* Remote address */
-	int			raddr_len;		/* Length of remote address */
 	ProtocolVersion pversion;	/* FE/BE protocol version in use */
 	char		sversion[8];	/* The first few bytes of server version */
 
diff --git a/src/port/getaddrinfo.c b/src/port/getaddrinfo.c
index 438f578f16dfd18968ed138f13a90fc92d8e9f74..409aef5e9caa9cfa6f8fade2e092368c99bb385d 100644
--- a/src/port/getaddrinfo.c
+++ b/src/port/getaddrinfo.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/port/getaddrinfo.c,v 1.3 2003/04/27 23:56:53 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/port/getaddrinfo.c,v 1.4 2003/06/12 07:36:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,28 +16,50 @@
 /* This is intended to be used in both frontend and backend, so use c.h */
 #include "c.h"
 
+#include <sys/types.h>
 #include <sys/socket.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#ifdef	HAVE_UNIX_SOCKETS
+#include <sys/un.h>
+#endif
 
 #include "getaddrinfo.h"
 
-
+/*
+ * get address info for ipv4 sockets.
+ *
+ *	Bugs:	- only one addrinfo is set even though hintp is NULL or
+ *		  ai_socktype is 0
+ *		- AI_CANONNAME is not supported.
+ *		- servname can only be a number, not text.
+ */
 int
 getaddrinfo(const char *node, const char *service,
-			const struct addrinfo *hints,
+			const struct addrinfo *hintp,
 			struct addrinfo **res)
 {
-	struct addrinfo *ai;
-	struct sockaddr_in sin, *psin;
+	struct addrinfo		*ai;
+	struct sockaddr_in	sin, *psin;
+	struct addrinfo		hints;
+
+	if (hintp == NULL)	
+	{
+		memset(&hints, 0, sizeof(hints));
+		hints.ai_family = AF_INET;
+		hints.ai_socktype = SOCK_STREAM;
+	}
+	else
+	{
+		memcpy(&hints, hintp, sizeof(hints));
+	}
 
-	if (!hints ||
-		(hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC))
+	if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC)
 		return EAI_FAMILY;
 
-	if (hints->ai_socktype != SOCK_STREAM)
-		return EAI_SOCKTYPE;
+	if (hints.ai_socktype == 0)
+		hints.ai_socktype = SOCK_STREAM;
 
 	if (!node && !service)
 		return EAI_NONAME;
@@ -50,9 +72,12 @@ getaddrinfo(const char *node, const char *service,
 	{
 		if (node[0] == '\0')
 			sin.sin_addr.s_addr = htonl(INADDR_ANY);
-		else if (hints->ai_flags & AI_NUMERICHOST)
+		else if (hints.ai_flags & AI_NUMERICHOST)
 		{
-			inet_aton(node, &sin.sin_addr);
+			if (!inet_aton(node, &sin.sin_addr))
+			{
+				return EAI_FAIL;
+			}
 		}
 		else
 		{
@@ -64,9 +89,8 @@ getaddrinfo(const char *node, const char *service,
 				switch (h_errno)
 				{
 					case HOST_NOT_FOUND:
-						return EAI_NONAME;
 					case NO_DATA:
-						return EAI_NODATA;
+						return EAI_NONAME;
 					case TRY_AGAIN:
 						return EAI_AGAIN;
 					case NO_RECOVERY:
@@ -75,14 +99,14 @@ getaddrinfo(const char *node, const char *service,
 				}
 			}
 			if (hp->h_addrtype != AF_INET)
-				return EAI_ADDRFAMILY;
+				return EAI_FAIL;
 
 			memcpy(&(sin.sin_addr), hp->h_addr, hp->h_length);
 		}
 	}
 	else
 	{
-		if (hints->ai_flags & AI_PASSIVE)
+		if (hints.ai_flags & AI_PASSIVE)
 			sin.sin_addr.s_addr = htonl(INADDR_ANY);
 		else
 			sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
@@ -90,10 +114,16 @@ getaddrinfo(const char *node, const char *service,
 
 	if (service)
 		sin.sin_port = htons((unsigned short) atoi(service));
+#if SALEN
+        sin.sin_len = sizeof(sin);
+#endif
 
 	ai = malloc(sizeof(*ai));
 	if (!ai)
+	{
 		return EAI_MEMORY;
+	}
+
 	psin = malloc(sizeof(*psin));
 	if (!psin)
 	{
@@ -103,9 +133,10 @@ getaddrinfo(const char *node, const char *service,
 
 	memcpy(psin, &sin, sizeof(*psin));
 
+	ai->ai_flags = 0;
 	ai->ai_family = AF_INET;
-	ai->ai_socktype = SOCK_STREAM;
-	ai->ai_protocol = IPPROTO_TCP;
+	ai->ai_socktype = hints.ai_socktype;
+	ai->ai_protocol = hints.ai_protocol;
 	ai->ai_addrlen = sizeof(*psin);
 	ai->ai_addr = (struct sockaddr *) psin;
 	ai->ai_canonname = NULL;
@@ -140,9 +171,6 @@ gai_strerror(int errcode)
 		case EAI_NONAME:
 			hcode = HOST_NOT_FOUND;
 			break;
-		case EAI_NODATA:
-			hcode = NO_DATA;
-			break;
 		case EAI_AGAIN:
 			hcode = TRY_AGAIN;
 			break;
@@ -160,8 +188,6 @@ gai_strerror(int errcode)
 	{
 		case EAI_NONAME:
 			return "Unknown host";
-		case EAI_NODATA:
-			return "No address associated with name";
 		case EAI_AGAIN:
 			return "Host name lookup failure";
 		case EAI_FAIL:
@@ -171,3 +197,82 @@ gai_strerror(int errcode)
 
 #endif /* HAVE_HSTRERROR */
 }
+
+/*
+ * Convert an address to a hostname.
+ * 
+ * Bugs:	- Only supports NI_NUMERICHOST and NI_NUMERICSERV
+ *		  It will never resolv a hostname.
+ *		- No IPv6 support.
+ */
+int
+getnameinfo(const struct sockaddr *sa, int salen,
+		char *node, int nodelen,
+		char *service, int servicelen, int flags)
+{
+	sa_family_t	family;
+	int		ret = -1;
+
+	/* Invalid arguments. */
+	if (sa == NULL || (node == NULL && service == NULL))
+	{
+		return EAI_FAIL;
+	}
+
+	/* We don't support those. */
+	if ((node && !(flags & NI_NUMERICHOST))
+		|| (service && !(flags & NI_NUMERICSERV)))
+	{
+		return EAI_FAIL;
+	}
+
+	family = sa->sa_family;
+#ifdef	HAVE_IPV6
+	if (family == AF_INET6)
+	{
+		return	EAI_FAMILY;
+	}
+#endif
+
+	if (service)
+	{
+		if (family == AF_INET)
+		{
+			ret = snprintf(service, servicelen, "%d",
+				ntohs(((struct sockaddr_in *)sa)->sin_port));
+		}
+#ifdef	HAVE_UNIX_SOCKETS
+		else if (family == AF_UNIX)
+		{
+			ret = snprintf(service, servicelen, "%s",
+				((struct sockaddr_un *)sa)->sun_path);
+		}
+#endif
+		if (ret == -1 || ret > servicelen)
+		{
+			return EAI_MEMORY;
+		}
+	}
+
+	if (node)
+	{
+		if (family == AF_INET)
+		{
+			char	*p;
+			p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
+			ret = snprintf(node, nodelen, "%s", p);
+		}
+#ifdef	HAVE_UNIX_SOCKETS
+		else if (family == AF_UNIX)
+		{
+			ret = snprintf(node, nodelen, "%s", "localhost");
+		}
+#endif
+		if (ret == -1 || ret > nodelen)
+		{
+			return EAI_MEMORY;
+		}
+	}
+
+	return 0;
+}