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;
+}