We have just finished porting the old KAME IPv6 patch over to
authorBruce Momjian <bruce@momjian.us>
Fri, 6 Dec 2002 03:46:37 +0000 (03:46 +0000)
committerBruce Momjian <bruce@momjian.us>
Fri, 6 Dec 2002 03:46:37 +0000 (03:46 +0000)
postgresql version 7.3, but yea... this patch adds full IPv6
support to postgres. I've tested it out on 7.2.3 and has
been running perfectly stable.

CREDITS:
 The KAME Project  (Initial patch)
 Nigel Kukard  <nkukard@lbsd.net>
 Johan Jordaan  <johanj@lando.co.za>

12 files changed:
configure
configure.in
src/backend/libpq/Makefile
src/backend/libpq/auth.c
src/backend/libpq/hba.c
src/backend/libpq/pg_hba.conf.sample
src/backend/libpq/pqcomm.c
src/backend/postmaster/postmaster.c
src/include/libpq/libpq.h
src/include/libpq/pqcomm.h
src/interfaces/libpq/Makefile
src/interfaces/libpq/fe-connect.c

index bb0a28bb081af2882897091bbcc61b0fdd00b84a..87c26d234f26e35667f876667079b206a4ca2fef 100755 (executable)
--- a/configure
+++ b/configure
@@ -15778,7 +15778,7 @@ fi
 ac_config_files="$ac_config_files GNUmakefile src/Makefile.global"
 
 
-ac_config_links="$ac_config_links src/backend/port/dynloader.c:src/backend/port/dynloader/${template}.c src/backend/port/pg_sema.c:${SEMA_IMPLEMENTATION} src/backend/port/pg_shmem.c:${SHMEM_IMPLEMENTATION} src/include/dynloader.h:src/backend/port/dynloader/${template}.h src/include/pg_config_os.h:src/include/port/${template}.h src/Makefile.port:src/makefiles/Makefile.${template}"
+ac_config_links="$ac_config_links src/backend/port/dynloader.c:src/backend/port/dynloader/${template}.c src/backend/port/pg_sema.c:${SEMA_IMPLEMENTATION} src/backend/port/pg_shmem.c:${SHMEM_IMPLEMENTATION} src/include/dynloader.h:src/backend/port/dynloader/${template}.h src/include/pg_config_os.h:src/include/port/${template}.h src/Makefile.port:src/makefiles/Makefile.${template} src/interfaces/libpq/v6util.c:src/backend/libpq/v6util.c"
 
 
 ac_config_headers="$ac_config_headers src/include/pg_config.h"
@@ -16266,6 +16266,7 @@ do
   "src/include/dynloader.h" ) CONFIG_LINKS="$CONFIG_LINKS src/include/dynloader.h:src/backend/port/dynloader/${template}.h" ;;
   "src/include/pg_config_os.h" ) CONFIG_LINKS="$CONFIG_LINKS src/include/pg_config_os.h:src/include/port/${template}.h" ;;
   "src/Makefile.port" ) CONFIG_LINKS="$CONFIG_LINKS src/Makefile.port:src/makefiles/Makefile.${template}" ;;
+  "src/interfaces/libpq/v6util.c" ) CONFIG_LINKS="$CONFIG_LINKS src/interfaces/libpq/v6util.c:src/backend/libpq/v6util.c" ;;
   "src/include/pg_config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config.h" ;;
   *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
 echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
index 68123ae74cc87af0f8232d4894b2b805e5dd31fe..fbc22aabbc791a294489cee4be88e8ae58f7f36a 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.219 2002/12/03 21:50:43 momjian Exp $
+dnl $Header: /cvsroot/pgsql/configure.in,v 1.220 2002/12/06 03:46:24 momjian Exp $
 dnl
 dnl Developers, please strive to achieve this order:
 dnl
@@ -1182,6 +1182,7 @@ AC_CONFIG_LINKS([
   src/include/dynloader.h:src/backend/port/dynloader/${template}.h
   src/include/pg_config_os.h:src/include/port/${template}.h
   src/Makefile.port:src/makefiles/Makefile.${template}
+  src/interfaces/libpq/v6util.c:src/backend/libpq/v6util.c
 ])
 
 AC_CONFIG_HEADERS([src/include/pg_config.h],
index cc4f750a7d68ba1e932bb36d47323449cede2808..6e7c1561b4df878817f0e4d07f701777a1b259e6 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for libpq subsystem (backend half of libpq interface)
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.33 2002/06/14 04:23:17 momjian Exp $
+#    $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.34 2002/12/06 03:46:24 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -15,7 +15,7 @@ include $(top_builddir)/src/Makefile.global
 # be-fsstubs is here for historical reasons, probably belongs elsewhere
 
 OBJS = be-fsstubs.o be-secure.o auth.o crypt.o hba.o md5.o pqcomm.o \
-       pqformat.o pqsignal.o
+       pqformat.o pqsignal.o v6util.o
 
 
 all: SUBSYS.o
index 0e0b64555bca402add255321b6d3f2d7629c326b..dfd6d1e93f56f7abc38a0070ba6336500d95c13a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.92 2002/12/03 22:09:19 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.93 2002/12/06 03:46:24 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -410,9 +410,12 @@ ClientAuthentication(Port *port)
                         */
                        {
                                const char *hostinfo = "localhost";
+                               char ip_hostinfo[INET6_ADDRSTRLEN];
+                               if (isAF_INETx(&port->raddr.sa) ){
+                                 hostinfo = SockAddr_ntop(&port->raddr, ip_hostinfo,
+                                                          INET6_ADDRSTRLEN, 1);
+                               }
 
-                               if (port->raddr.sa.sa_family == AF_INET)
-                                       hostinfo = inet_ntoa(port->raddr.in.sin_addr);
                                elog(FATAL,
                                "No pg_hba.conf entry for host %s, user %s, database %s",
                                         hostinfo, port->user, port->database);
index 396347945e39ba94eb93d8037e2566d73e94e239..5cdf60da96a60c83617be02b545589055342e459 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.88 2002/12/03 21:50:44 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.89 2002/12/06 03:46:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -582,9 +582,8 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
        }
        else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0)
        {
-               struct in_addr file_ip_addr,
-                                       mask;
-
+               SockAddr file_ip_addr, mask;
+               
                if (strcmp(token, "hostssl") == 0)
                {
 #ifdef USE_SSL
@@ -619,16 +618,25 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
                if (!line)
                        goto hba_syntax;
                token = lfirst(line);
-               if (!inet_aton(token, &file_ip_addr))
-                       goto hba_syntax;
+
+               if(SockAddr_pton(&file_ip_addr, token, strlen(token)) < 0){
+                 goto hba_syntax;
+               }
 
                /* Read the mask field. */
                line = lnext(line);
                if (!line)
                        goto hba_syntax;
                token = lfirst(line);
-               if (!inet_aton(token, &mask))
-                       goto hba_syntax;
+
+               if(SockAddr_pton(&mask, token, strlen(token)) < 0){
+                 goto hba_syntax;
+               }
+
+
+               if(file_ip_addr.sa.sa_family != mask.sa.sa_family){
+                 goto hba_syntax;
+               }
 
                /* Read the rest of the line. */
                line = lnext(line);
@@ -639,8 +647,7 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
                        goto hba_syntax;
 
                /* Must meet network restrictions */
-               if (port->raddr.sa.sa_family != AF_INET ||
-                       ((file_ip_addr.s_addr ^ port->raddr.in.sin_addr.s_addr) & mask.s_addr) != 0)
+               if (!isAF_INETx(&port->raddr) || !rangeSockAddr(&port->raddr, &file_ip_addr, &mask))
                        return;
        }
        else
index 5338c79104b07782bf007de42d64e054ebe4dd32..4ff29977c62efce003a0618d26e0a18d45f21ef4 100644 (file)
@@ -44,5 +44,6 @@
 
 # TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK           METHOD
 
-local   all         all                                             trust
-host    all         all         127.0.0.1         255.255.255.255   trust
+local   all         all                                                                trust
+host    all         all         127.0.0.1         255.255.255.255                      trust
+host    all         all         ::1               ffff:ffff:ffff:fff:ffff:ffff:ffff    trust
index 62e8bd44cd5e931f34799bfd9de2667f9f8b7708..757a8a72ce6728f2870727532660d7f989c603e8 100644 (file)
@@ -29,7 +29,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $Id: pqcomm.c,v 1.141 2002/09/04 23:31:34 tgl Exp $
+ *     $Id: pqcomm.c,v 1.142 2002/12/06 03:46:28 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -85,6 +85,11 @@ extern ssize_t secure_read(Port *, void *, size_t);
 extern ssize_t secure_write(Port *, const void *, size_t);
 
 static void pq_close(void);
+#ifdef HAVE_UNIX_SOCKETS
+int StreamServerPortSubAFUNIX1(unsigned short portNumber,
+                              char *unixSocketName );
+int StreamServerPortSubAFUNIX2(void);
+#endif /* HAVE_UNIX_SOCKETS */
 
 
 /*
@@ -182,171 +187,199 @@ int
 StreamServerPort(int family, char *hostName, unsigned short portNumber,
                                 char *unixSocketName, int *fdP)
 {
-       SockAddr        saddr;
-       int                     fd,
-                               err;
-       int                     maxconn;
-       size_t          len = 0;
-       int                     one = 1;
+  int                  fd,
+                       err;
+  int                  maxconn;
+  int                  one = 1;
 
-       Assert(family == AF_INET || family == AF_UNIX);
+  int                   ret;
+  struct addrinfo*      addrs  = NULL;
+  struct addrinfo       hint;
+  char                  portNumberStr[64];
+  char*                 service = portNumberStr;
+  char*                 hostn = (hostName[0] == '\0')? NULL : hostName;
 
-       if ((fd = socket(family, SOCK_STREAM, 0)) < 0)
-       {
-               elog(LOG, "StreamServerPort: socket() failed: %m");
-               return STATUS_ERROR;
-       }
+  Assert(family == AF_INET6 || family == AF_INET || family == AF_UNIX);
 
-       if (family == AF_INET)
-       {
-               if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
-                                               sizeof(one))) == -1)
-               {
-                       elog(LOG, "StreamServerPort: setsockopt(SO_REUSEADDR) failed: %m");
-                       return STATUS_ERROR;
-               }
-       }
+  memset(&hint, 0, sizeof(hint));
+  hint.ai_family   = family;
+  hint.ai_flags    = AI_PASSIVE;
+  hint.ai_socktype = SOCK_STREAM;
 
-       MemSet((char *) &saddr, 0, sizeof(saddr));
-       saddr.sa.sa_family = family;
+  snprintf(portNumberStr, sizeof(portNumberStr)/sizeof(char),
+          "%d", portNumber);
 
 #ifdef HAVE_UNIX_SOCKETS
-       if (family == AF_UNIX)
-       {
-               UNIXSOCK_PATH(saddr.un, portNumber, unixSocketName);
-               len = UNIXSOCK_LEN(saddr.un);
-               strcpy(sock_path, saddr.un.sun_path);
-
-               /*
-                * Grab an interlock file associated with the socket file.
-                */
-               if (!CreateSocketLockFile(sock_path, true))
-                       return STATUS_ERROR;
-
-               /*
-                * Once we have the interlock, we can safely delete any
-                * pre-existing socket file to avoid failure at bind() time.
-                */
-               unlink(sock_path);
-       }
+  if (family == AF_UNIX) {
+    if(StreamServerPortSubAFUNIX1(portNumber, unixSocketName) != STATUS_OK){
+      return STATUS_ERROR;
+    }
+    service = sock_path;
+  }
 #endif   /* HAVE_UNIX_SOCKETS */
 
-       if (family == AF_INET)
-       {
-               /* TCP/IP socket */
-               if (hostName[0] == '\0')
-                       saddr.in.sin_addr.s_addr = htonl(INADDR_ANY);
-               else
-               {
-                       struct hostent *hp;
 
-                       hp = gethostbyname(hostName);
-                       if ((hp == NULL) || (hp->h_addrtype != AF_INET))
-                       {
-                               elog(LOG, "StreamServerPort: gethostbyname(%s) failed",
-                                        hostName);
-                               return STATUS_ERROR;
-                       }
-                       memmove((char *) &(saddr.in.sin_addr), (char *) hp->h_addr,
-                                       hp->h_length);
-               }
 
-               saddr.in.sin_port = htons(portNumber);
-               len = sizeof(struct sockaddr_in);
-       }
-
-       err = bind(fd, (struct sockaddr *) & saddr.sa, len);
-       if (err < 0)
-       {
-               if (family == AF_UNIX)
-                       elog(LOG, "StreamServerPort: bind() failed: %m\n"
-                                "\tIs another postmaster already running on port %d?\n"
-                                "\tIf not, remove socket node (%s) and retry.",
-                                (int) portNumber, sock_path);
-               else
-                       elog(LOG, "StreamServerPort: bind() failed: %m\n"
-                                "\tIs another postmaster already running on port %d?\n"
-                                "\tIf not, wait a few seconds and retry.",
-                                (int) portNumber);
-               return STATUS_ERROR;
-       }
+  ret = getaddrinfo2(hostn, service, &hint, &addrs);
+  if(ret || addrs == NULL){
+    elog(LOG, "FATAL: StreamServerPort: getaddrinfo2() failed: %s\n",
+            gai_strerror(ret));
+    freeaddrinfo2(hint.ai_family, addrs);
+    return STATUS_ERROR;
+  }
+
+
+  /** YY DEBUG
+  if(addrs->ai_family == AF_UNIX){
+    printf("%s-%s-%s \n", "debug: AF_UNIX!", unixSocketName, hostName);
+  }
+  else {
+    printf("%s", "debug: NOT AF_UNIX!\n");
+  }
+  fflush(stdout);
+  **/
+
+  if( (fd = socket(addrs->ai_family, SOCK_STREAM, 0)) < 0){
+    elog(LOG, "FATAL: StreamServerPort: socket() failed: %s\n",
+            strerror(errno));
+    freeaddrinfo2(hint.ai_family, addrs);
+    return STATUS_ERROR;
+  }
+
+  if( isAF_INETx2(family) ){
+    if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, 
+                   sizeof(one) )) == -1 ){
+      elog(LOG, "FATAL: StreamServerPort: setsockopt(SO_REUSEADDR) failed: %s\n",
+              strerror(errno));
+      freeaddrinfo2(hint.ai_family, addrs);
+      return STATUS_ERROR;
+    }
+  }
+
+
+  err = bind(fd, addrs->ai_addr, addrs->ai_addrlen);
+  if(err < 0){
+    elog(LOG, "FATAL: StreamServerPort: bind() failed: %s\n"
+            "\tIs another postmaster already running on port %d?\n",
+            strerror(errno), (int) portNumber);
+    if (family == AF_UNIX)
+      elog(LOG, "\tIf not, remove socket node (%s) and retry.\n",
+              sock_path);
+    else
+      elog(LOG, "\tIf not, wait a few seconds and retry.\n");
+    freeaddrinfo2(hint.ai_family, addrs);
+    return STATUS_ERROR;
+  }
 
 #ifdef HAVE_UNIX_SOCKETS
-       if (family == AF_UNIX)
-       {
-               /* Arrange to unlink the socket file at exit */
-               on_proc_exit(StreamDoUnlink, 0);
-
-               /*
-                * Fix socket ownership/permission if requested.  Note we must do
-                * this before we listen() to avoid a window where unwanted
-                * connections could get accepted.
-                */
-               Assert(Unix_socket_group);
-               if (Unix_socket_group[0] != '\0')
-               {
-                       char       *endptr;
-                       unsigned long int val;
-                       gid_t           gid;
-
-                       val = strtoul(Unix_socket_group, &endptr, 10);
-                       if (*endptr == '\0')
-                       {
-                               /* numeric group id */
-                               gid = val;
-                       }
-                       else
-                       {
-                               /* convert group name to id */
-                               struct group *gr;
-
-                               gr = getgrnam(Unix_socket_group);
-                               if (!gr)
-                               {
-                                       elog(LOG, "No such group as '%s'",
-                                                Unix_socket_group);
-                                       return STATUS_ERROR;
-                               }
-                               gid = gr->gr_gid;
-                       }
-                       if (chown(sock_path, -1, gid) == -1)
-                       {
-                               elog(LOG, "Could not set group of %s: %m",
-                                        sock_path);
-                               return STATUS_ERROR;
-                       }
-               }
+  if (family == AF_UNIX){
+    if(StreamServerPortSubAFUNIX2() != STATUS_OK){
+      freeaddrinfo2(hint.ai_family, addrs);
+      return STATUS_ERROR;
+    }
+  }
+#endif
 
-               if (chmod(sock_path, Unix_socket_permissions) == -1)
-               {
-                       elog(LOG, "Could not set permissions on %s: %m",
-                                sock_path);
-                       return STATUS_ERROR;
-               }
-       }
-#endif   /* HAVE_UNIX_SOCKETS */
+  /*
+   * 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, "FATAL: StreamServerPort: listen() failed: %s\n",
+            strerror(errno));
+    freeaddrinfo2(hint.ai_family, addrs);
+    return STATUS_ERROR;
+  }
+
+  *fdP = fd;
+  freeaddrinfo2(hint.ai_family, addrs);
+  return STATUS_OK;
 
-       /*
-        * 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, "StreamServerPort: listen() failed: %m");
-               return STATUS_ERROR;
-       }
+#ifdef HAVE_UNIX_SOCKETS
+int StreamServerPortSubAFUNIX1(unsigned short portNumber,
+                              char *unixSocketName )
+{
+  SockAddr     saddr;
+  int           len;
+
+  MemSet((char *) &saddr, 0, sizeof(saddr));
+  
+  UNIXSOCK_PATH(saddr.un, portNumber, unixSocketName);
+  len = UNIXSOCK_LEN(saddr.un);
+  strcpy(sock_path, saddr.un.sun_path);
+  
+  /*
+   * Grab an interlock file associated with the socket file.
+   */
+  if (!CreateSocketLockFile(sock_path, true))
+    return STATUS_ERROR;
+  
+  /*
+   * Once we have the interlock, we can safely delete any
+   * pre-existing socket file to avoid failure at bind() time.
+   */
+  unlink(sock_path);
+
+  return STATUS_OK;
+}
 
-       *fdP = fd;
 
-       return STATUS_OK;
+int StreamServerPortSubAFUNIX2(void)
+{
+  /* Arrange to unlink the socket file at exit */
+  on_proc_exit(StreamDoUnlink, 0);
+  
+  /*
+   * Fix socket ownership/permission if requested.  Note we must do
+   * this before we listen() to avoid a window where unwanted
+   * connections could get accepted.
+   */
+  Assert(Unix_socket_group);
+  if (Unix_socket_group[0] != '\0')  {
+    char          *endptr;
+    unsigned long int val;
+    gid_t              gid;
+    
+    val = strtoul(Unix_socket_group, &endptr, 10);
+    if (*endptr == '\0'){     /* numeric group id */
+      gid = val;
+    }
+    else {                    /* convert group name to id */
+      struct group *gr;
+      gr = getgrnam(Unix_socket_group);
+      if (!gr) {
+       elog(LOG, "FATAL:  no such group '%s'\n",
+                Unix_socket_group);
+       return STATUS_ERROR;
+      }
+      gid = gr->gr_gid;
+    }
+    if (chown(sock_path, -1, gid) == -1){
+      elog(LOG, "FATAL:  could not set group of %s: %s\n",
+              sock_path, strerror(errno));
+      return STATUS_ERROR;
+    }
+  }
+
+  if (chmod(sock_path, Unix_socket_permissions) == -1){
+       elog(LOG, "FATAL:  could not set permissions on %s: %s\n",
+            sock_path, strerror(errno));
+    return STATUS_ERROR;
+  }
+  return STATUS_OK;
 }
 
+#endif   /* HAVE_UNIX_SOCKETS */
+
+
 /*
  * StreamConnection -- create a new connection with client using
  *             server port.
@@ -391,8 +424,20 @@ StreamConnection(int server_fd, Port *port)
                return STATUS_ERROR;
        }
 
+       /* DEBUG YY
+       { 
+         char l_hostinfo[INET6_ADDRSTRLEN];
+         char r_hostinfo[INET6_ADDRSTRLEN];
+         SockAddr_ntop(&port->laddr, l_hostinfo, INET6_ADDRSTRLEN, 1);
+         SockAddr_ntop(&port->raddr, r_hostinfo, INET6_ADDRSTRLEN, 1);
+         printf("StreamConnect() l: %s r: %s\n", l_hostinfo, r_hostinfo);
+         printf("StreamConnect() l: %d r: %d\n", port->laddr.sa.sa_family, 
+                port->raddr.sa.sa_family);
+       }
+       */
+
        /* select NODELAY and KEEPALIVE options if it's a TCP connection */
-       if (port->laddr.sa.sa_family == AF_INET)
+       if ( isAF_INETx(&port->laddr) )
        {
                int                     on = 1;
 
index 8f34a3fd2dcd5dd2cadbb7b6c49268431e6bc0e2..077878449035f03ed11e3c38b4033dad316444ea 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.299 2002/11/21 06:36:08 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.300 2002/12/06 03:46:29 momjian Exp $
  *
  * NOTES
  *
@@ -669,7 +669,7 @@ PostmasterMain(int argc, char *argv[])
         */
        if (NetServer)
        {
-               status = StreamServerPort(AF_INET, VirtualHost,
+               status = StreamServerPort(AF_INET6, VirtualHost,
                                                                  (unsigned short) PostPortNumber,
                                                                  UnixSocketDir,
                                                                  &ServerSock_INET);
@@ -2091,13 +2091,14 @@ DoBackend(Port *port)
        /*
         * Get the remote host name and port for logging and status display.
         */
-       if (port->raddr.sa.sa_family == AF_INET)
+       if (isAF_INETx(&port->raddr))
        {
                unsigned short remote_port;
                char       *host_addr;
+               char       ip_hostinfo[INET6_ADDRSTRLEN]; 
 
                remote_port = ntohs(port->raddr.in.sin_port);
-               host_addr = inet_ntoa(port->raddr.in.sin_addr);
+               host_addr = SockAddr_ntop(&port->raddr, ip_hostinfo, INET6_ADDRSTRLEN, 1);
 
                remote_host = NULL;
 
index 5e4db4d24300bedf793959271e83f71c5fcb0a44..b0b1041be18110de8068ab82042dd93824fc00c7 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.52 2002/09/04 23:31:35 tgl Exp $
+ * $Id: libpq.h,v 1.53 2002/12/06 03:46:32 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,7 @@
 
 #include "lib/stringinfo.h"
 #include "libpq/libpq-be.h"
+#include "libpq/v6util.h"
 
 /* ----------------
  * PQArgBlock
index 4066c23e0e46d5f83beee2d53416b4a7ed5e6cdc..a84978c570596c2bade82620a31fe2b7909f6150 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.70 2002/09/04 20:31:42 momjian Exp $
+ * $Id: pqcomm.h,v 1.71 2002/12/06 03:46:33 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,6 +47,7 @@ typedef union SockAddr
 {
        struct sockaddr sa;
        struct sockaddr_in in;
+       struct sockaddr_in6 in6;
        struct sockaddr_un un;
 } SockAddr;
 
index 6537f86074daf421608589bfe527926809923aa2..a91611cd306c356396f6d6af1003230fe429b270 100644 (file)
@@ -4,7 +4,7 @@
 #
 # Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/interfaces/libpq/Makefile,v 1.66 2002/12/04 18:14:11 momjian Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/libpq/Makefile,v 1.67 2002/12/06 03:46:37 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -23,6 +23,7 @@ override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) -DFRONTEND -DSYSCONFDIR='"$(sysconf
 OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
       pqexpbuffer.o dllist.o md5.o pqsignal.o fe-secure.o \
       wchar.o encnames.o \
+      v6util.o \
       $(filter inet_aton.o snprintf.o strerror.o, $(LIBOBJS))
 
 
index 7cdd2466624469daecb16563fb419eb4d6972b52..36782ecf70f347c940b0227a446193295901b62c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.213 2002/10/24 23:35:55 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.214 2002/12/06 03:46:37 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,6 +39,9 @@
 #include <arpa/inet.h>
 #endif
 
+#include "libpq/v6util.h"
+
+
 #ifndef HAVE_STRDUP
 #include "strdup.h"
 #endif
@@ -786,6 +789,15 @@ connectDBStart(PGconn *conn)
 {
        int                     portno,
                                family;
+       struct addrinfo*        addrs         = NULL;
+       struct addrinfo*        addr_cur      = NULL;
+       struct addrinfo         hint;
+       const char*             node          = NULL;
+       const char*             unix_node     = "unix";
+       char                    portNoStr[64];
+       int   ret;
+       int   sockfd;
+
 
 #ifdef USE_SSL
        StartupPacket np;                       /* Used to negotiate SSL connection */
@@ -815,101 +827,67 @@ connectDBStart(PGconn *conn)
 
        MemSet((char *) &conn->raddr, 0, sizeof(conn->raddr));
 
-       if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
-       {
-               /* Using pghostaddr avoids a hostname lookup */
-               /* Note that this supports IPv4 only */
-               struct in_addr addr;
-
-               if (!inet_aton(conn->pghostaddr, &addr))
-               {
-                       printfPQExpBuffer(&conn->errorMessage,
-                                                         libpq_gettext("invalid host address: %s\n"),
-                                                         conn->pghostaddr);
-                       goto connect_errReturn;
-               }
-
-               family = AF_INET;
-
-               memmove((char *) &(conn->raddr.in.sin_addr),
-                               (char *) &addr, sizeof(addr));
+       MemSet(&hint, 0, sizeof(hint));
+       hint.ai_socktype = SOCK_STREAM;
+       if(conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0'){
+         node = conn->pghostaddr;
+         hint.ai_family = AF_UNSPEC;
        }
-       else if (conn->pghost != NULL && conn->pghost[0] != '\0')
-       {
-               /* Using pghost, so we have to look-up the hostname */
-               struct hostent *hp;
-
-               hp = gethostbyname(conn->pghost);
-               if ((hp == NULL) || (hp->h_addrtype != AF_INET))
-               {
-                       printfPQExpBuffer(&conn->errorMessage,
-                                                         libpq_gettext("unknown host name: %s\n"),
-                                                         conn->pghost);
-                       goto connect_errReturn;
-               }
-               family = AF_INET;
-
-               memmove((char *) &(conn->raddr.in.sin_addr),
-                               (char *) hp->h_addr,
-                               hp->h_length);
+       else if (conn->pghost != NULL && conn->pghost[0] != '\0'){
+         node = conn->pghost;
+         hint.ai_family = AF_UNSPEC;
        }
-       else
-       {
-               /* pghostaddr and pghost are NULL, so use Unix domain socket */
-               family = AF_UNIX;
+#ifdef HAVE_UNIX_SOCKETS
+       else {
+         node = unix_node;
+         hint.ai_family = AF_UNIX;
        }
+#endif   /* HAVE_UNIX_SOCKETS */
 
-       /* Set family */
-       conn->raddr.sa.sa_family = family;
-
-       /* Set port number */
        if (conn->pgport != NULL && conn->pgport[0] != '\0')
-               portno = atoi(conn->pgport);
+         portno = atoi(conn->pgport);
        else
-               portno = DEF_PGPORT;
-
-       if (family == AF_INET)
-       {
-               conn->raddr.in.sin_port = htons((unsigned short) (portno));
-               conn->raddr_len = sizeof(struct sockaddr_in);
+         portno = DEF_PGPORT;
+       
+       if(hint.ai_family == AF_UNSPEC){
+         snprintf(portNoStr, sizeof(portNoStr)/sizeof(char),
+                  "%d", portno);
        }
 #ifdef HAVE_UNIX_SOCKETS
-       else
-       {
-               UNIXSOCK_PATH(conn->raddr.un, portno, conn->pgunixsocket);
-               conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un);
+       else {
+         UNIXSOCK_PATH(conn->raddr.un, portno, conn->pgunixsocket);
+         conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un);
+         strcpy(portNoStr, conn->raddr.un.sun_path);
 #ifdef USE_SSL
                /* Don't bother requesting SSL over a Unix socket */
                conn->allow_ssl_try = false;
                conn->require_ssl = false;
 #endif
        }
-#endif
-
-       /* Open a socket */
-       if ((conn->sock = socket(family, SOCK_STREAM, 0)) < 0)
-       {
-               printfPQExpBuffer(&conn->errorMessage,
-                                                 libpq_gettext("could not create socket: %s\n"),
-                                                 SOCK_STRERROR(SOCK_ERRNO));
-               goto connect_errReturn;
-       }
-
-       /*
-        * Set the right options. Normally, we need nonblocking I/O, and we
-        * don't want delay of outgoing data for AF_INET sockets.  If we are
-        * using SSL, then we need the blocking I/O (XXX Can this be fixed?).
-        */
-
-       if (family == AF_INET)
-       {
-               if (!connectNoDelay(conn))
-                       goto connect_errReturn;
+#endif   /* HAVE_UNIX_SOCKETS */
+
+       ret = getaddrinfo2(node, portNoStr, &hint, &addrs);
+       if(ret || addrs == NULL){
+         printfPQExpBuffer(&conn->errorMessage,
+                           libpq_gettext("failed to getaddrinfo(): %s\n"),
+                           gai_strerror(ret) );
+         goto connect_errReturn;
        }
-
+       addr_cur = addrs;
+       do {
+         sockfd = socket(addr_cur->ai_family, addr_cur->ai_socktype, 
+                         addr_cur->ai_protocol);
+         if(sockfd < 0){
+           continue;
+         }
+         conn->sock = sockfd;
+         if (isAF_INETx2(addr_cur->ai_family) ){
+           if (!connectNoDelay(conn))
+             goto connect_errReturn;
+         }
 #if !defined(USE_SSL)
-       if (connectMakeNonblocking(conn) == 0)
-               goto connect_errReturn;
+         if (connectMakeNonblocking(conn) == 0)
+           goto connect_errReturn;
 #endif
 
        /* ----------
@@ -922,31 +900,42 @@ connectDBStart(PGconn *conn)
         * ----------
         */
 retry1:
-       if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0)
-       {
+         if(connect(sockfd, addr_cur->ai_addr, addr_cur->ai_addrlen) == 0){
+           /* We're connected already */
+           conn->status = CONNECTION_MADE;
+           break;
+         }
+         else {
                if (SOCK_ERRNO == EINTR)
                        /* Interrupted system call - we'll just try again */
                        goto retry1;
 
-               if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || SOCK_ERRNO == 0)
-               {
-                       /*
-                        * This is fine - we're in non-blocking mode, and the
-                        * connection is in progress.
-                        */
-                       conn->status = CONNECTION_STARTED;
-               }
-               else
-               {
-                       /* Something's gone wrong */
-                       connectFailureMessage(conn, SOCK_ERRNO);
-                       goto connect_errReturn;
-               }
+           if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || SOCK_ERRNO == 0){
+
+               /*
+                * This is fine - we're in non-blocking mode, and the
+                * connection is in progress.
+                */
+               conn->status = CONNECTION_STARTED;
+               break;
+           }
+         }
+         close(sockfd);
+       } while( (addr_cur = addr_cur->ai_next) != NULL);
+
+       if(addr_cur == NULL){
+         printfPQExpBuffer(&conn->errorMessage,
+                           libpq_gettext("could not create socket: %s\n"),
+                           SOCK_STRERROR(SOCK_ERRNO));
+
+         goto connect_errReturn;
        }
-       else
-       {
-               /* We're connected already */
-               conn->status = CONNECTION_MADE;
+       else {
+         family = addr_cur->ai_family;
+         memmove(&conn->raddr, addr_cur->ai_addr, addr_cur->ai_addrlen);
+         conn->raddr_len = addr_cur->ai_addrlen;
+         freeaddrinfo2(hint.ai_family, addrs);
+         addrs = NULL;
        }
 
 #ifdef USE_SSL
@@ -1038,7 +1027,9 @@ connect_errReturn:
                conn->sock = -1;
        }
        conn->status = CONNECTION_BAD;
-
+       if(addrs != NULL){
+         freeaddrinfo2(hint.ai_family, addrs);
+       }
        return 0;
 }