]> granicus.if.org Git - postgresql/commitdiff
IPv6 cleanups.
authorBruce Momjian <bruce@momjian.us>
Thu, 12 Jun 2003 07:36:51 +0000 (07:36 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 12 Jun 2003 07:36:51 +0000 (07:36 +0000)
Kurt Roeckx
Andrew Dunstan

20 files changed:
config/c-library.m4
configure
configure.in
src/backend/libpq/auth.c
src/backend/libpq/hba.c
src/backend/libpq/ip.c
src/backend/libpq/pg_hba.conf.sample
src/backend/libpq/pqcomm.c
src/backend/postmaster/pgstat.c
src/backend/postmaster/postmaster.c
src/include/getaddrinfo.h
src/include/libpq/ip.h
src/include/libpq/libpq.h
src/include/libpq/pqcomm.h
src/include/pg_config.h.in
src/include/pg_config_manual.h
src/include/port/bsdi.h
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/libpq-int.h
src/port/getaddrinfo.c

index f482f9936cb6e003be90bb475b098c6ca1ad4754..bd632ed7cd36b6bb9f36c00403d4c3671a331fa3 100644 (file)
@@ -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.
index 906e9b33b32efe9f456a18ed5ce7ec4e12276b8e..2056980885ac069d705c10f55484421fa2fe323f 100755 (executable)
--- 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
index 5881542a4cf4868da45a792b960457ad6f39b86a..8ccff55630980891128a293a3f4a9547cbb57fed 100644 (file)
@@ -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], [], [],
index 2b0d2d65a8b9d00dad770c4e163736c3ad82ea89..46965e3bcb3acccc6f2cde27a0312e5c004b1f64 100644 (file)
@@ -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);
index 4310261a16bd94fa65b896df88009f1fdc33aef9..c277c90d1b9d6af34a054576cb9ea025b58803b1 100644 (file)
@@ -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:
index 203317be4eb77b186f6ed376bc9047929fe6c184..59bee56e212e026ed5e4bde6cbbbfd2e26a9dda8 100644 (file)
@@ -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
 #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 */
index 1116debbc1acf07c85aae9a6c87401cac1a460ae..52c0bd4d73da038660afdbede9555dbaac0f0382 100644 (file)
@@ -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
+
index ea4ff64468643774728f103f61fd14b07ed4be50..2cd2c9223f71f40ec997f21427165d88034da74d 100644 (file)
@@ -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)
                {
index 2b8708fc5d2e326f064a547f744209d58ecbc42c..a0495fff8551872d2fcf03eda41e79777f70c9aa 100644 (file)
@@ -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;
 
                        /*
index 5b16d06a994bf2ea449bc0c478191cff170a23b2..e32a668bc715cd0211683bf8de5a24befdba2f4e 100644 (file)
@@ -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);
 }
index 2b47d613e9967f067f8b83fdddaaccbaee52b905..416dc65fb1ef6bf2cabf9e2f31fba0e1ad79ad94 100644 (file)
@@ -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 */
 
index b43d9972663b555584c0eebfb96e86eedbd45e57..b770d33bfe391274d0c74614811b12f5bd8f8228 100644 (file)
@@ -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 */
index cbe0b646e74e3092fcfa6836c9e27f76d9ae262d..9f72b7e432c042137129f4fa596868f4d213309d 100644 (file)
@@ -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);
index eac9867391b3e7d4391c876c378da322dc0ad09c..ed41464c2ccee0156281d83dd92a9ddaa300db6f 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 #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.
  *
index b20cecf194876283ae890cae9043842321b05771..a15ca6b6a6f8e0834f5a81a35ed2a9bdf3eb8acb 100644 (file)
 /* 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
 
 /* 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
 
index e8699c2f4a02c0308cfd9e4333a2132dff52224e..3bf316a5805c33059bd80fc57178fad1104c8781 100644 (file)
@@ -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 $
  *------------------------------------------------------------------------
  */
 
 #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
 
 /*
index e5ba051f239b6168c397e6d0e7638a0013600e57..3a2aa59d096556bd96492f7577fe64ae5d100ae3 100644 (file)
@@ -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
index 64e39c7baf3e6844b36d66e5cba2a7b8b70078de..4445bd217883de6def2feb66d37b0eaeccde324d 100644 (file)
@@ -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 */
index f710f58b8e49bf20f6ecd6e7cbb531760aee2332..47dbbb4af5f60e478ae5497444f3693ee0937f2c 100644 (file)
@@ -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 */
 
index 438f578f16dfd18968ed138f13a90fc92d8e9f74..409aef5e9caa9cfa6f8fade2e092368c99bb385d 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 /* 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;
+}