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