Tweak the existing special case for AIX in pg_getaddrinfo_all() to handle
authorTom Lane
Fri, 23 Jan 2009 19:58:06 +0000 (19:58 +0000)
committerTom Lane
Fri, 23 Jan 2009 19:58:06 +0000 (19:58 +0000)
yet another failure case in AIX's getaddrinfo().  Per report and patch
by Andrew Chernow.

src/backend/libpq/ip.c

index ef3ef04902cc5caa36502f6201c58724ca50e59f..67e92654d1c043aac83caee82005756595606947 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/libpq/ip.c,v 1.43 2009/01/01 17:23:42 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/libpq/ip.c,v 1.44 2009/01/23 19:58:06 tgl Exp $
  *
  * This file and the IPV6 implementation were initially provided by
  * Nigel Kukard , Linux Based Systems Design
@@ -74,36 +74,46 @@ pg_getaddrinfo_all(const char *hostname, const char *servname,
        return getaddrinfo_unix(servname, hintp, result);
 #endif
 
+#ifndef _AIX
    /* NULL has special meaning to getaddrinfo(). */
    rc = getaddrinfo((!hostname || hostname[0] == '\0') ? NULL : hostname,
                     servname, hintp, result);
 
-#ifdef _AIX
+#else /* _AIX */
 
    /*
-    * It seems some versions of AIX's getaddrinfo don't reliably zero
-    * sin_port when servname is NULL, so clean up after it.
+    * Various versions of AIX have various bugs in getaddrinfo()'s handling
+    * of the servname parameter, including failing entirely if it's not NULL
+    * and failing to zero sin_port when it is NULL :-(.  Avoid these by
+    * always passing NULL and handling the port number for ourselves.
     */
-   if (servname == NULL && rc == 0)
+   rc = getaddrinfo((!hostname || hostname[0] == '\0') ? NULL : hostname,
+                    NULL, hintp, result);
+
+   if (rc == 0)
    {
        struct addrinfo *addr;
+       unsigned short port = 0;
+
+       if (servname && *servname)
+           port = atoi(servname);
 
        for (addr = *result; addr; addr = addr->ai_next)
        {
            switch (addr->ai_family)
            {
                case AF_INET:
-                   ((struct sockaddr_in *) addr->ai_addr)->sin_port = htons(0);
+                   ((struct sockaddr_in *) addr->ai_addr)->sin_port = htons(port);
                    break;
 #ifdef HAVE_IPV6
                case AF_INET6:
-                   ((struct sockaddr_in6 *) addr->ai_addr)->sin6_port = htons(0);
+                   ((struct sockaddr_in6 *) addr->ai_addr)->sin6_port = htons(port);
                    break;
 #endif
            }
        }
    }
-#endif
+#endif /* _AIX */
 
    return rc;
 }