Re: duplicate connection failure messages

Поиск
Список
Период
Сортировка
От Bruce Momjian
Тема Re: duplicate connection failure messages
Дата
Msg-id 201011202307.oAKN7vl13470@momjian.us
обсуждение исходный текст
Ответ на Re: duplicate connection failure messages  (Tom Lane <tgl@sss.pgh.pa.us>)
Ответы Re: duplicate connection failure messages  (Bruce Momjian <bruce@momjian.us>)
Re: duplicate connection failure messages  (Peter Eisentraut <peter_e@gmx.net>)
Список pgsql-hackers
Tom Lane wrote:
> Bruce Momjian <bruce@momjian.us> writes:
> > I assume you are suggesting to use our inet_net_ntop() even if the
> > system has inet_ntop().
>
> If you're going to have code to do the former, it doesn't seem to be
> worth the trouble to also have code that does the latter ...

OK, we will not call inet_ntop() at all.  I moved the CIDR part of
adt/inet_net_ntop.c into adt/inet_cidr_ntop.c, and moved the remaining
"net" part to /port/inet_net_ntop.c.

I then changed all uses of inet_ntoa to use inet_net_ntop().  While this
churn would perhaps not be warranted just to allow for better error
messages, I found pg_getaddrinfo_all() being called from
libpq::connectDBStart(), which makes it not thread-safe.  I am not
excited about backpatching it but it is a threading bug.

The output is as expected:

    $ psql -h localhost test
    psql: could not connect to server: Connection refused
            Is the server running on host "localhost" (127.0.0.1) and accepting
            TCP/IP connections on port 5432?
    $ psql -h 127.0.0.1 test
    psql: could not connect to server: Connection refused
            Is the server running on host "127.0.0.1" and accepting
            TCP/IP connections on port 5432?

--
  Bruce Momjian  <bruce@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + It's impossible for everything to be true. +
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a911c50..814c27a 100644
*** /tmp/pgrevert.8208/Z2NPcb_libpq.sgml    Sat Nov 20 18:06:46 2010
--- doc/src/sgml/libpq.sgml    Sat Nov 20 17:11:04 2010
*************** PGconn *PQconnectdbParams(const char **k
*** 170,180 ****
             If <literal>host</> is specified without <literal>hostaddr</>,
             a host name lookup occurs.
             If <literal>hostaddr</> is specified without <literal>host</>,
!            the value for <literal>hostaddr</> gives the server address.
             The connection attempt will fail in any of the cases where a
             host name is required.
             If both <literal>host</> and <literal>hostaddr</> are specified,
!            the value for <literal>hostaddr</> gives the server address.
             The value for <literal>host</> is ignored unless needed for
             authentication or verification purposes, in which case it will be
             used as the host name.  Note that authentication is likely to fail
--- 170,180 ----
             If <literal>host</> is specified without <literal>hostaddr</>,
             a host name lookup occurs.
             If <literal>hostaddr</> is specified without <literal>host</>,
!            the value for <literal>hostaddr</> gives the server network address.
             The connection attempt will fail in any of the cases where a
             host name is required.
             If both <literal>host</> and <literal>hostaddr</> are specified,
!            the value for <literal>hostaddr</> gives the server network address.
             The value for <literal>host</> is ignored unless needed for
             authentication or verification purposes, in which case it will be
             used as the host name.  Note that authentication is likely to fail
diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile
index be272b5..ce28abd 100644
*** /tmp/pgrevert.8208/zxOcga_Makefile    Sat Nov 20 18:06:46 2010
--- src/backend/utils/adt/Makefile    Sat Nov 20 17:11:04 2010
*************** OBJS = acl.o arrayfuncs.o array_userfunc
*** 23,29 ****
      oid.o oracle_compat.o pseudotypes.o rowtypes.o \
      regexp.o regproc.o ruleutils.o selfuncs.o \
      tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
!     network.o mac.o inet_net_ntop.o inet_net_pton.o \
      ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
      ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o trigfuncs.o \
      tsginidx.o tsgistidx.o tsquery.o tsquery_cleanup.o tsquery_gist.o \
--- 23,29 ----
      oid.o oracle_compat.o pseudotypes.o rowtypes.o \
      regexp.o regproc.o ruleutils.o selfuncs.o \
      tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
!     network.o mac.o inet_cidr_ntop.o inet_net_pton.o \
      ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
      ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o trigfuncs.o \
      tsginidx.o tsgistidx.o tsquery.o tsquery_cleanup.o tsquery_gist.o \
diff --git a/src/include/port.h b/src/include/port.h
index 2048768..0cfbed8 100644
*** /tmp/pgrevert.8208/DZNlKd_port.h    Sat Nov 20 18:06:46 2010
--- src/include/port.h    Sat Nov 20 17:11:42 2010
*************** extern void qsort_arg(void *base, size_t
*** 437,440 ****
--- 437,444 ----
  /* port/chklocale.c */
  extern int    pg_get_encoding_from_locale(const char *ctype);

+ /* port/inet_net_ntop.c */
+ extern char *inet_net_ntop(int af, const void *src, int bits,
+               char *dst, size_t size);
+
  #endif   /* PG_PORT_H */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index ae267ab..88eac70 100644
*** /tmp/pgrevert.8208/1NPEOc_builtins.h    Sat Nov 20 18:06:46 2010
--- src/include/utils/builtins.h    Sat Nov 20 17:11:42 2010
*************** extern Datum chr (PG_FUNCTION_ARGS);
*** 793,801 ****
  extern Datum repeat(PG_FUNCTION_ARGS);
  extern Datum ascii(PG_FUNCTION_ARGS);

! /* inet_net_ntop.c */
! extern char *inet_net_ntop(int af, const void *src, int bits,
!               char *dst, size_t size);
  extern char *inet_cidr_ntop(int af, const void *src, int bits,
                 char *dst, size_t size);

--- 793,799 ----
  extern Datum repeat(PG_FUNCTION_ARGS);
  extern Datum ascii(PG_FUNCTION_ARGS);

! /* inet_cidr_ntop.c */
  extern char *inet_cidr_ntop(int af, const void *src, int bits,
                 char *dst, size_t size);

diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 8f318a1..8011604 100644
*** /tmp/pgrevert.8208/7EVSqc_fe-connect.c    Sat Nov 20 18:06:46 2010
--- src/interfaces/libpq/fe-connect.c    Sat Nov 20 17:42:54 2010
*************** connectFailureMessage(PGconn *conn, int
*** 960,968 ****
      else
  #endif   /* HAVE_UNIX_SOCKETS */
      {
          appendPQExpBuffer(&conn->errorMessage,
                            libpq_gettext("could not connect to server: %s\n"
!                      "\tIs the server running on host \"%s\" and accepting\n"
                                          "\tTCP/IP connections on port %s?\n"),
                            SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
                            conn->pghostaddr
--- 960,987 ----
      else
  #endif   /* HAVE_UNIX_SOCKETS */
      {
+         char    host_addr[NI_MAXHOST];
+         bool     display_host_addr;
+         struct sockaddr_in *host_addr_struct = (struct sockaddr_in *)
+                                                 &conn->raddr.addr;
+
+         /*
+          *    Optionally display the network address with the hostname.
+          *    This is useful to distinguish between IPv4 and IPv6 connections.
+          */
+         if (conn->pghostaddr != NULL)
+             strlcpy(host_addr, conn->pghostaddr, NI_MAXHOST);
+         else if (inet_net_ntop(conn->addr_cur->ai_family, &host_addr_struct->sin_addr,
+                  host_addr_struct->sin_family == AF_INET ? 32 : 128,
+                  host_addr, sizeof(host_addr)) == NULL)
+             strcpy(host_addr, "???");
+
+         display_host_addr = !conn->pghostaddr &&
+                             strcmp(conn->pghost, host_addr) != 0;
+
          appendPQExpBuffer(&conn->errorMessage,
                            libpq_gettext("could not connect to server: %s\n"
!                      "\tIs the server running on host \"%s\" %s%s%sand accepting\n"
                                          "\tTCP/IP connections on port %s?\n"),
                            SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
                            conn->pghostaddr
*************** connectFailureMessage(PGconn *conn, int
*** 970,975 ****
--- 989,998 ----
                            : (conn->pghost
                               ? conn->pghost
                               : "???"),
+                           /* display the IP address only if not already output */
+                           display_host_addr ? "(" : "",
+                           display_host_addr ? host_addr : "",
+                           display_host_addr ? ") " : "",
                            conn->pgport);
      }
  }
diff --git a/src/port/Makefile b/src/port/Makefile
index 327ec72..711f633 100644
*** /tmp/pgrevert.8208/9HEr9d_Makefile    Sat Nov 20 18:06:46 2010
--- src/port/Makefile    Sat Nov 20 17:11:04 2010
*************** include $(top_builddir)/src/Makefile.glo
*** 30,36 ****
  override CPPFLAGS := -I$(top_builddir)/src/port -DFRONTEND $(CPPFLAGS)
  LIBS += $(PTHREAD_LIBS)

! OBJS = $(LIBOBJS) chklocale.o dirmod.o exec.o noblock.o path.o \
      pgsleep.o pgstrcasecmp.o qsort.o qsort_arg.o sprompt.o thread.o
  ifneq (,$(filter $(PORTNAME),cygwin win32))
  OBJS += pipe.o
--- 30,36 ----
  override CPPFLAGS := -I$(top_builddir)/src/port -DFRONTEND $(CPPFLAGS)
  LIBS += $(PTHREAD_LIBS)

! OBJS = $(LIBOBJS) chklocale.o dirmod.o exec.o inet_net_ntop.o noblock.o path.o \
      pgsleep.o pgstrcasecmp.o qsort.o qsort_arg.o sprompt.o thread.o
  ifneq (,$(filter $(PORTNAME),cygwin win32))
  OBJS += pipe.o
diff --git a/src/port/getaddrinfo.c b/src/port/getaddrinfo.c
index f867744..807f5bd 100644
*** /tmp/pgrevert.8208/vneSVc_getaddrinfo.c    Sat Nov 20 18:06:46 2010
--- src/port/getaddrinfo.c    Sat Nov 20 17:21:02 2010
*************** getnameinfo(const struct sockaddr * sa,
*** 388,403 ****

      if (node)
      {
-         int            ret = -1;
-
          if (sa->sa_family == AF_INET)
          {
!             char       *p;
!
!             p = inet_ntoa(((struct sockaddr_in *) sa)->sin_addr);
!             ret = snprintf(node, nodelen, "%s", p);
          }
!         if (ret == -1 || ret > nodelen)
              return EAI_MEMORY;
      }

--- 388,401 ----

      if (node)
      {
          if (sa->sa_family == AF_INET)
          {
!             if (inet_net_ntop(AF_INET, ((struct sockaddr_in *) sa)->sin_addr,
!                 sa->sa_family == AF_INET ? 32 : 128,
!                 node, nodelen) == NULL)
!             return EAI_MEMORY;
          }
!         else
              return EAI_MEMORY;
      }

diff --git a/src/backend/utils/adt/inet_cidr_ntop.c b/src/backend/utils/adt/inet_cidr_ntop.c
index ...5f2a3d3 .
*** /dev/null    Sat Nov 20 18:04:30 2010
--- src/backend/utils/adt/inet_cidr_ntop.c    Sat Nov 20 17:16:32 2010
***************
*** 0 ****
--- 1,295 ----
+ /*
+  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+  * Copyright (c) 1996,1999 by Internet Software Consortium.
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+  * copyright notice and this permission notice appear in all copies.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *
+  *      src/backend/utils/adt/inet_net_ntop.c
+  */
+
+ #if defined(LIBC_SCCS) && !defined(lint)
+ static const char rcsid[] = "Id: inet_net_ntop.c,v 1.1.2.2 2004/03/09 09:17:27 marka Exp $";
+ #endif
+
+ #include "postgres.h"
+
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+
+ #include "utils/builtins.h"
+ #include "utils/inet.h"
+
+
+ #ifdef SPRINTF_CHAR
+ #define SPRINTF(x) strlen(sprintf/**/x)
+ #else
+ #define SPRINTF(x) ((size_t)sprintf x)
+ #endif
+
+ static char *inet_cidr_ntop_ipv4(const u_char *src, int bits,
+                     char *dst, size_t size);
+ static char *inet_cidr_ntop_ipv6(const u_char *src, int bits,
+                     char *dst, size_t size);
+
+ /*
+  * char *
+  * inet_cidr_ntop(af, src, bits, dst, size)
+  *    convert network number from network to presentation format.
+  *    generates CIDR style result always.
+  * return:
+  *    pointer to dst, or NULL if an error occurred (check errno).
+  * author:
+  *    Paul Vixie (ISC), July 1996
+  */
+ char *
+ inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size)
+ {
+     switch (af)
+     {
+         case PGSQL_AF_INET:
+             return (inet_cidr_ntop_ipv4(src, bits, dst, size));
+         case PGSQL_AF_INET6:
+             return (inet_cidr_ntop_ipv6(src, bits, dst, size));
+         default:
+             errno = EAFNOSUPPORT;
+             return (NULL);
+     }
+ }
+
+
+ /*
+  * static char *
+  * inet_cidr_ntop_ipv4(src, bits, dst, size)
+  *    convert IPv4 network number from network to presentation format.
+  *    generates CIDR style result always.
+  * return:
+  *    pointer to dst, or NULL if an error occurred (check errno).
+  * note:
+  *    network byte order assumed.  this means 192.5.5.240/28 has
+  *    0b11110000 in its fourth octet.
+  * author:
+  *    Paul Vixie (ISC), July 1996
+  */
+ static char *
+ inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
+ {
+     char       *odst = dst;
+     char       *t;
+     u_int        m;
+     int            b;
+
+     if (bits < 0 || bits > 32)
+     {
+         errno = EINVAL;
+         return (NULL);
+     }
+
+     if (bits == 0)
+     {
+         if (size < sizeof "0")
+             goto emsgsize;
+         *dst++ = '0';
+         size--;
+         *dst = '\0';
+     }
+
+     /* Format whole octets. */
+     for (b = bits / 8; b > 0; b--)
+     {
+         if (size <= sizeof "255.")
+             goto emsgsize;
+         t = dst;
+         dst += SPRINTF((dst, "%u", *src++));
+         if (b > 1)
+         {
+             *dst++ = '.';
+             *dst = '\0';
+         }
+         size -= (size_t) (dst - t);
+     }
+
+     /* Format partial octet. */
+     b = bits % 8;
+     if (b > 0)
+     {
+         if (size <= sizeof ".255")
+             goto emsgsize;
+         t = dst;
+         if (dst != odst)
+             *dst++ = '.';
+         m = ((1 << b) - 1) << (8 - b);
+         dst += SPRINTF((dst, "%u", *src & m));
+         size -= (size_t) (dst - t);
+     }
+
+     /* Format CIDR /width. */
+     if (size <= sizeof "/32")
+         goto emsgsize;
+     dst += SPRINTF((dst, "/%u", bits));
+     return (odst);
+
+ emsgsize:
+     errno = EMSGSIZE;
+     return (NULL);
+ }
+
+ /*
+  * static char *
+  * inet_cidr_ntop_ipv6(src, bits, fakebits, dst, size)
+  *    convert IPv6 network number from network to presentation format.
+  *    generates CIDR style result always. Picks the shortest representation
+  *    unless the IP is really IPv4.
+  *    always prints specified number of bits (bits).
+  * return:
+  *    pointer to dst, or NULL if an error occurred (check errno).
+  * note:
+  *    network byte order assumed.  this means 192.5.5.240/28 has
+  *    0x11110000 in its fourth octet.
+  * author:
+  *    Vadim Kogan (UCB), June 2001
+  *    Original version (IPv4) by Paul Vixie (ISC), July 1996
+  */
+
+ static char *
+ inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
+ {
+     u_int        m;
+     int            b;
+     int            p;
+     int            zero_s,
+                 zero_l,
+                 tmp_zero_s,
+                 tmp_zero_l;
+     int            i;
+     int            is_ipv4 = 0;
+     unsigned char inbuf[16];
+     char        outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
+     char       *cp;
+     int            words;
+     u_char       *s;
+
+     if (bits < 0 || bits > 128)
+     {
+         errno = EINVAL;
+         return (NULL);
+     }
+
+     cp = outbuf;
+
+     if (bits == 0)
+     {
+         *cp++ = ':';
+         *cp++ = ':';
+         *cp = '\0';
+     }
+     else
+     {
+         /* Copy src to private buffer.    Zero host part. */
+         p = (bits + 7) / 8;
+         memcpy(inbuf, src, p);
+         memset(inbuf + p, 0, 16 - p);
+         b = bits % 8;
+         if (b != 0)
+         {
+             m = ~0 << (8 - b);
+             inbuf[p - 1] &= m;
+         }
+
+         s = inbuf;
+
+         /* how many words need to be displayed in output */
+         words = (bits + 15) / 16;
+         if (words == 1)
+             words = 2;
+
+         /* Find the longest substring of zero's */
+         zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0;
+         for (i = 0; i < (words * 2); i += 2)
+         {
+             if ((s[i] | s[i + 1]) == 0)
+             {
+                 if (tmp_zero_l == 0)
+                     tmp_zero_s = i / 2;
+                 tmp_zero_l++;
+             }
+             else
+             {
+                 if (tmp_zero_l && zero_l < tmp_zero_l)
+                 {
+                     zero_s = tmp_zero_s;
+                     zero_l = tmp_zero_l;
+                     tmp_zero_l = 0;
+                 }
+             }
+         }
+
+         if (tmp_zero_l && zero_l < tmp_zero_l)
+         {
+             zero_s = tmp_zero_s;
+             zero_l = tmp_zero_l;
+         }
+
+         if (zero_l != words && zero_s == 0 && ((zero_l == 6) ||
+                           ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) ||
+                            ((zero_l == 7 && s[14] != 0 && s[15] != 1)))))
+             is_ipv4 = 1;
+
+         /* Format whole words. */
+         for (p = 0; p < words; p++)
+         {
+             if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l)
+             {
+                 /* Time to skip some zeros */
+                 if (p == zero_s)
+                     *cp++ = ':';
+                 if (p == words - 1)
+                     *cp++ = ':';
+                 s++;
+                 s++;
+                 continue;
+             }
+
+             if (is_ipv4 && p > 5)
+             {
+                 *cp++ = (p == 6) ? ':' : '.';
+                 cp += SPRINTF((cp, "%u", *s++));
+                 /* we can potentially drop the last octet */
+                 if (p != 7 || bits > 120)
+                 {
+                     *cp++ = '.';
+                     cp += SPRINTF((cp, "%u", *s++));
+                 }
+             }
+             else
+             {
+                 if (cp != outbuf)
+                     *cp++ = ':';
+                 cp += SPRINTF((cp, "%x", *s * 256 + s[1]));
+                 s += 2;
+             }
+         }
+     }
+     /* Format CIDR /width. */
+     (void) SPRINTF((cp, "/%u", bits));
+     if (strlen(outbuf) + 1 > size)
+         goto emsgsize;
+     strcpy(dst, outbuf);
+
+     return (dst);
+
+ emsgsize:
+     errno = EMSGSIZE;
+     return (NULL);
+ }
diff --git a/src/backend/utils/adt/inet_net_ntop.c b/src/backend/utils/adt/inet_net_ntop.c
index 3d7fb65..e69de29 100644
*** /tmp/pgrevert.8208/zi7lid_inet_net_ntop.c    Sat Nov 20 18:06:46 2010
--- /dev/null    Sat Nov 20 18:04:30 2010
***************
*** 1,530 ****
- /*
-  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
-  * Copyright (c) 1996,1999 by Internet Software Consortium.
-  *
-  * Permission to use, copy, modify, and distribute this software for any
-  * purpose with or without fee is hereby granted, provided that the above
-  * copyright notice and this permission notice appear in all copies.
-  *
-  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-  *
-  *      src/backend/utils/adt/inet_net_ntop.c
-  */
-
- #if defined(LIBC_SCCS) && !defined(lint)
- static const char rcsid[] = "Id: inet_net_ntop.c,v 1.1.2.2 2004/03/09 09:17:27 marka Exp $";
- #endif
-
- #include "postgres.h"
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
-
- #include "utils/builtins.h"
- #include "utils/inet.h"
-
-
- #define NS_IN6ADDRSZ 16
- #define NS_INT16SZ 2
-
- #ifdef SPRINTF_CHAR
- #define SPRINTF(x) strlen(sprintf/**/x)
- #else
- #define SPRINTF(x) ((size_t)sprintf x)
- #endif
-
- static char *inet_net_ntop_ipv4(const u_char *src, int bits,
-                    char *dst, size_t size);
- static char *inet_cidr_ntop_ipv4(const u_char *src, int bits,
-                     char *dst, size_t size);
- static char *inet_net_ntop_ipv6(const u_char *src, int bits,
-                    char *dst, size_t size);
- static char *inet_cidr_ntop_ipv6(const u_char *src, int bits,
-                     char *dst, size_t size);
-
- /*
-  * char *
-  * inet_cidr_ntop(af, src, bits, dst, size)
-  *    convert network number from network to presentation format.
-  *    generates CIDR style result always.
-  * return:
-  *    pointer to dst, or NULL if an error occurred (check errno).
-  * author:
-  *    Paul Vixie (ISC), July 1996
-  */
- char *
- inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size)
- {
-     switch (af)
-     {
-         case PGSQL_AF_INET:
-             return (inet_cidr_ntop_ipv4(src, bits, dst, size));
-         case PGSQL_AF_INET6:
-             return (inet_cidr_ntop_ipv6(src, bits, dst, size));
-         default:
-             errno = EAFNOSUPPORT;
-             return (NULL);
-     }
- }
-
-
- /*
-  * static char *
-  * inet_cidr_ntop_ipv4(src, bits, dst, size)
-  *    convert IPv4 network number from network to presentation format.
-  *    generates CIDR style result always.
-  * return:
-  *    pointer to dst, or NULL if an error occurred (check errno).
-  * note:
-  *    network byte order assumed.  this means 192.5.5.240/28 has
-  *    0b11110000 in its fourth octet.
-  * author:
-  *    Paul Vixie (ISC), July 1996
-  */
- static char *
- inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
- {
-     char       *odst = dst;
-     char       *t;
-     u_int        m;
-     int            b;
-
-     if (bits < 0 || bits > 32)
-     {
-         errno = EINVAL;
-         return (NULL);
-     }
-
-     if (bits == 0)
-     {
-         if (size < sizeof "0")
-             goto emsgsize;
-         *dst++ = '0';
-         size--;
-         *dst = '\0';
-     }
-
-     /* Format whole octets. */
-     for (b = bits / 8; b > 0; b--)
-     {
-         if (size <= sizeof "255.")
-             goto emsgsize;
-         t = dst;
-         dst += SPRINTF((dst, "%u", *src++));
-         if (b > 1)
-         {
-             *dst++ = '.';
-             *dst = '\0';
-         }
-         size -= (size_t) (dst - t);
-     }
-
-     /* Format partial octet. */
-     b = bits % 8;
-     if (b > 0)
-     {
-         if (size <= sizeof ".255")
-             goto emsgsize;
-         t = dst;
-         if (dst != odst)
-             *dst++ = '.';
-         m = ((1 << b) - 1) << (8 - b);
-         dst += SPRINTF((dst, "%u", *src & m));
-         size -= (size_t) (dst - t);
-     }
-
-     /* Format CIDR /width. */
-     if (size <= sizeof "/32")
-         goto emsgsize;
-     dst += SPRINTF((dst, "/%u", bits));
-     return (odst);
-
- emsgsize:
-     errno = EMSGSIZE;
-     return (NULL);
- }
-
- /*
-  * static char *
-  * inet_cidr_ntop_ipv6(src, bits, fakebits, dst, size)
-  *    convert IPv6 network number from network to presentation format.
-  *    generates CIDR style result always. Picks the shortest representation
-  *    unless the IP is really IPv4.
-  *    always prints specified number of bits (bits).
-  * return:
-  *    pointer to dst, or NULL if an error occurred (check errno).
-  * note:
-  *    network byte order assumed.  this means 192.5.5.240/28 has
-  *    0x11110000 in its fourth octet.
-  * author:
-  *    Vadim Kogan (UCB), June 2001
-  *    Original version (IPv4) by Paul Vixie (ISC), July 1996
-  */
-
- static char *
- inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
- {
-     u_int        m;
-     int            b;
-     int            p;
-     int            zero_s,
-                 zero_l,
-                 tmp_zero_s,
-                 tmp_zero_l;
-     int            i;
-     int            is_ipv4 = 0;
-     unsigned char inbuf[16];
-     char        outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
-     char       *cp;
-     int            words;
-     u_char       *s;
-
-     if (bits < 0 || bits > 128)
-     {
-         errno = EINVAL;
-         return (NULL);
-     }
-
-     cp = outbuf;
-
-     if (bits == 0)
-     {
-         *cp++ = ':';
-         *cp++ = ':';
-         *cp = '\0';
-     }
-     else
-     {
-         /* Copy src to private buffer.    Zero host part. */
-         p = (bits + 7) / 8;
-         memcpy(inbuf, src, p);
-         memset(inbuf + p, 0, 16 - p);
-         b = bits % 8;
-         if (b != 0)
-         {
-             m = ~0 << (8 - b);
-             inbuf[p - 1] &= m;
-         }
-
-         s = inbuf;
-
-         /* how many words need to be displayed in output */
-         words = (bits + 15) / 16;
-         if (words == 1)
-             words = 2;
-
-         /* Find the longest substring of zero's */
-         zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0;
-         for (i = 0; i < (words * 2); i += 2)
-         {
-             if ((s[i] | s[i + 1]) == 0)
-             {
-                 if (tmp_zero_l == 0)
-                     tmp_zero_s = i / 2;
-                 tmp_zero_l++;
-             }
-             else
-             {
-                 if (tmp_zero_l && zero_l < tmp_zero_l)
-                 {
-                     zero_s = tmp_zero_s;
-                     zero_l = tmp_zero_l;
-                     tmp_zero_l = 0;
-                 }
-             }
-         }
-
-         if (tmp_zero_l && zero_l < tmp_zero_l)
-         {
-             zero_s = tmp_zero_s;
-             zero_l = tmp_zero_l;
-         }
-
-         if (zero_l != words && zero_s == 0 && ((zero_l == 6) ||
-                           ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) ||
-                            ((zero_l == 7 && s[14] != 0 && s[15] != 1)))))
-             is_ipv4 = 1;
-
-         /* Format whole words. */
-         for (p = 0; p < words; p++)
-         {
-             if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l)
-             {
-                 /* Time to skip some zeros */
-                 if (p == zero_s)
-                     *cp++ = ':';
-                 if (p == words - 1)
-                     *cp++ = ':';
-                 s++;
-                 s++;
-                 continue;
-             }
-
-             if (is_ipv4 && p > 5)
-             {
-                 *cp++ = (p == 6) ? ':' : '.';
-                 cp += SPRINTF((cp, "%u", *s++));
-                 /* we can potentially drop the last octet */
-                 if (p != 7 || bits > 120)
-                 {
-                     *cp++ = '.';
-                     cp += SPRINTF((cp, "%u", *s++));
-                 }
-             }
-             else
-             {
-                 if (cp != outbuf)
-                     *cp++ = ':';
-                 cp += SPRINTF((cp, "%x", *s * 256 + s[1]));
-                 s += 2;
-             }
-         }
-     }
-     /* Format CIDR /width. */
-     (void) SPRINTF((cp, "/%u", bits));
-     if (strlen(outbuf) + 1 > size)
-         goto emsgsize;
-     strcpy(dst, outbuf);
-
-     return (dst);
-
- emsgsize:
-     errno = EMSGSIZE;
-     return (NULL);
- }
-
-
- /*
-  * char *
-  * inet_net_ntop(af, src, bits, dst, size)
-  *    convert host/network address from network to presentation format.
-  *    "src"'s size is determined from its "af".
-  * return:
-  *    pointer to dst, or NULL if an error occurred (check errno).
-  * note:
-  *    192.5.5.1/28 has a nonzero host part, which means it isn't a network
-  *    as called for by inet_net_pton() but it can be a host address with
-  *    an included netmask.
-  * author:
-  *    Paul Vixie (ISC), October 1998
-  */
- char *
- inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
- {
-     switch (af)
-     {
-         case PGSQL_AF_INET:
-             return (inet_net_ntop_ipv4(src, bits, dst, size));
-         case PGSQL_AF_INET6:
-             return (inet_net_ntop_ipv6(src, bits, dst, size));
-         default:
-             errno = EAFNOSUPPORT;
-             return (NULL);
-     }
- }
-
- /*
-  * static char *
-  * inet_net_ntop_ipv4(src, bits, dst, size)
-  *    convert IPv4 network address from network to presentation format.
-  *    "src"'s size is determined from its "af".
-  * return:
-  *    pointer to dst, or NULL if an error occurred (check errno).
-  * note:
-  *    network byte order assumed.  this means 192.5.5.240/28 has
-  *    0b11110000 in its fourth octet.
-  * author:
-  *    Paul Vixie (ISC), October 1998
-  */
- static char *
- inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
- {
-     char       *odst = dst;
-     char       *t;
-     int            len = 4;
-     int            b;
-
-     if (bits < 0 || bits > 32)
-     {
-         errno = EINVAL;
-         return (NULL);
-     }
-
-     /* Always format all four octets, regardless of mask length. */
-     for (b = len; b > 0; b--)
-     {
-         if (size <= sizeof ".255")
-             goto emsgsize;
-         t = dst;
-         if (dst != odst)
-             *dst++ = '.';
-         dst += SPRINTF((dst, "%u", *src++));
-         size -= (size_t) (dst - t);
-     }
-
-     /* don't print masklen if 32 bits */
-     if (bits != 32)
-     {
-         if (size <= sizeof "/32")
-             goto emsgsize;
-         dst += SPRINTF((dst, "/%u", bits));
-     }
-
-     return (odst);
-
- emsgsize:
-     errno = EMSGSIZE;
-     return (NULL);
- }
-
- static int
- decoct(const u_char *src, int bytes, char *dst, size_t size)
- {
-     char       *odst = dst;
-     char       *t;
-     int            b;
-
-     for (b = 1; b <= bytes; b++)
-     {
-         if (size <= sizeof "255.")
-             return (0);
-         t = dst;
-         dst += SPRINTF((dst, "%u", *src++));
-         if (b != bytes)
-         {
-             *dst++ = '.';
-             *dst = '\0';
-         }
-         size -= (size_t) (dst - t);
-     }
-     return (dst - odst);
- }
-
- static char *
- inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
- {
-     /*
-      * Note that int32_t and int16_t need only be "at least" large enough to
-      * contain a value of the specified size.  On some systems, like Crays,
-      * there is no such thing as an integer variable with 16 bits. Keep this
-      * in mind if you think this function should have been coded to use
-      * pointer overlays.  All the world's not a VAX.
-      */
-     char        tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
-     char       *tp;
-     struct
-     {
-         int            base,
-                     len;
-     }            best, cur;
-     u_int        words[NS_IN6ADDRSZ / NS_INT16SZ];
-     int            i;
-
-     if ((bits < -1) || (bits > 128))
-     {
-         errno = EINVAL;
-         return (NULL);
-     }
-
-     /*
-      * Preprocess: Copy the input (bytewise) array into a wordwise array. Find
-      * the longest run of 0x00's in src[] for :: shorthanding.
-      */
-     memset(words, '\0', sizeof words);
-     for (i = 0; i < NS_IN6ADDRSZ; i++)
-         words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
-     best.base = -1;
-     cur.base = -1;
-     best.len = 0;
-     cur.len = 0;
-     for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
-     {
-         if (words[i] == 0)
-         {
-             if (cur.base == -1)
-                 cur.base = i, cur.len = 1;
-             else
-                 cur.len++;
-         }
-         else
-         {
-             if (cur.base != -1)
-             {
-                 if (best.base == -1 || cur.len > best.len)
-                     best = cur;
-                 cur.base = -1;
-             }
-         }
-     }
-     if (cur.base != -1)
-     {
-         if (best.base == -1 || cur.len > best.len)
-             best = cur;
-     }
-     if (best.base != -1 && best.len < 2)
-         best.base = -1;
-
-     /*
-      * Format the result.
-      */
-     tp = tmp;
-     for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
-     {
-         /* Are we inside the best run of 0x00's? */
-         if (best.base != -1 && i >= best.base &&
-             i < (best.base + best.len))
-         {
-             if (i == best.base)
-                 *tp++ = ':';
-             continue;
-         }
-         /* Are we following an initial run of 0x00s or any real hex? */
-         if (i != 0)
-             *tp++ = ':';
-         /* Is this address an encapsulated IPv4? */
-         if (i == 6 && best.base == 0 && (best.len == 6 ||
-                                      (best.len == 7 && words[7] != 0x0001) ||
-                                       (best.len == 5 && words[5] == 0xffff)))
-         {
-             int            n;
-
-             n = decoct(src + 12, 4, tp, sizeof tmp - (tp - tmp));
-             if (n == 0)
-             {
-                 errno = EMSGSIZE;
-                 return (NULL);
-             }
-             tp += strlen(tp);
-             break;
-         }
-         tp += SPRINTF((tp, "%x", words[i]));
-     }
-
-     /* Was it a trailing run of 0x00's? */
-     if (best.base != -1 && (best.base + best.len) ==
-         (NS_IN6ADDRSZ / NS_INT16SZ))
-         *tp++ = ':';
-     *tp = '\0';
-
-     if (bits != -1 && bits != 128)
-         tp += SPRINTF((tp, "/%u", bits));
-
-     /*
-      * Check for overflow, copy, and we're done.
-      */
-     if ((size_t) (tp - tmp) > size)
-     {
-         errno = EMSGSIZE;
-         return (NULL);
-     }
-     strcpy(dst, tmp);
-     return (dst);
- }
--- 0 ----
diff --git a/src/port/inet_net_ntop.c b/src/port/inet_net_ntop.c
index ...02d3a7c .
*** /dev/null    Sat Nov 20 18:04:30 2010
--- src/port/inet_net_ntop.c    Sat Nov 20 17:14:44 2010
***************
*** 0 ****
--- 1,275 ----
+ /*
+  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+  * Copyright (c) 1996,1999 by Internet Software Consortium.
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+  * copyright notice and this permission notice appear in all copies.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *
+  *      src/backend/utils/adt/inet_net_ntop.c
+  */
+
+ #if defined(LIBC_SCCS) && !defined(lint)
+ static const char rcsid[] = "Id: inet_net_ntop.c,v 1.1.2.2 2004/03/09 09:17:27 marka Exp $";
+ #endif
+
+ #include "postgres.h"
+
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+
+ #include "utils/inet.h"
+
+
+ #define NS_IN6ADDRSZ 16
+ #define NS_INT16SZ 2
+
+ #ifdef SPRINTF_CHAR
+ #define SPRINTF(x) strlen(sprintf/**/x)
+ #else
+ #define SPRINTF(x) ((size_t)sprintf x)
+ #endif
+
+ static char *inet_net_ntop_ipv4(const u_char *src, int bits,
+                    char *dst, size_t size);
+ static char *inet_net_ntop_ipv6(const u_char *src, int bits,
+                    char *dst, size_t size);
+
+
+ /*
+  * char *
+  * inet_net_ntop(af, src, bits, dst, size)
+  *    convert host/network address from network to presentation format.
+  *    "src"'s size is determined from its "af".
+  * return:
+  *    pointer to dst, or NULL if an error occurred (check errno).
+  * note:
+  *    192.5.5.1/28 has a nonzero host part, which means it isn't a network
+  *    as called for by inet_net_pton() but it can be a host address with
+  *    an included netmask.
+  * author:
+  *    Paul Vixie (ISC), October 1998
+  */
+ char *
+ inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
+ {
+     switch (af)
+     {
+         case PGSQL_AF_INET:
+             return (inet_net_ntop_ipv4(src, bits, dst, size));
+         case PGSQL_AF_INET6:
+             return (inet_net_ntop_ipv6(src, bits, dst, size));
+         default:
+             errno = EAFNOSUPPORT;
+             return (NULL);
+     }
+ }
+
+ /*
+  * static char *
+  * inet_net_ntop_ipv4(src, bits, dst, size)
+  *    convert IPv4 network address from network to presentation format.
+  *    "src"'s size is determined from its "af".
+  * return:
+  *    pointer to dst, or NULL if an error occurred (check errno).
+  * note:
+  *    network byte order assumed.  this means 192.5.5.240/28 has
+  *    0b11110000 in its fourth octet.
+  * author:
+  *    Paul Vixie (ISC), October 1998
+  */
+ static char *
+ inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
+ {
+     char       *odst = dst;
+     char       *t;
+     int            len = 4;
+     int            b;
+
+     if (bits < 0 || bits > 32)
+     {
+         errno = EINVAL;
+         return (NULL);
+     }
+
+     /* Always format all four octets, regardless of mask length. */
+     for (b = len; b > 0; b--)
+     {
+         if (size <= sizeof ".255")
+             goto emsgsize;
+         t = dst;
+         if (dst != odst)
+             *dst++ = '.';
+         dst += SPRINTF((dst, "%u", *src++));
+         size -= (size_t) (dst - t);
+     }
+
+     /* don't print masklen if 32 bits */
+     if (bits != 32)
+     {
+         if (size <= sizeof "/32")
+             goto emsgsize;
+         dst += SPRINTF((dst, "/%u", bits));
+     }
+
+     return (odst);
+
+ emsgsize:
+     errno = EMSGSIZE;
+     return (NULL);
+ }
+
+ static int
+ decoct(const u_char *src, int bytes, char *dst, size_t size)
+ {
+     char       *odst = dst;
+     char       *t;
+     int            b;
+
+     for (b = 1; b <= bytes; b++)
+     {
+         if (size <= sizeof "255.")
+             return (0);
+         t = dst;
+         dst += SPRINTF((dst, "%u", *src++));
+         if (b != bytes)
+         {
+             *dst++ = '.';
+             *dst = '\0';
+         }
+         size -= (size_t) (dst - t);
+     }
+     return (dst - odst);
+ }
+
+ static char *
+ inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
+ {
+     /*
+      * Note that int32_t and int16_t need only be "at least" large enough to
+      * contain a value of the specified size.  On some systems, like Crays,
+      * there is no such thing as an integer variable with 16 bits. Keep this
+      * in mind if you think this function should have been coded to use
+      * pointer overlays.  All the world's not a VAX.
+      */
+     char        tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
+     char       *tp;
+     struct
+     {
+         int            base,
+                     len;
+     }            best, cur;
+     u_int        words[NS_IN6ADDRSZ / NS_INT16SZ];
+     int            i;
+
+     if ((bits < -1) || (bits > 128))
+     {
+         errno = EINVAL;
+         return (NULL);
+     }
+
+     /*
+      * Preprocess: Copy the input (bytewise) array into a wordwise array. Find
+      * the longest run of 0x00's in src[] for :: shorthanding.
+      */
+     memset(words, '\0', sizeof words);
+     for (i = 0; i < NS_IN6ADDRSZ; i++)
+         words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+     best.base = -1;
+     cur.base = -1;
+     best.len = 0;
+     cur.len = 0;
+     for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
+     {
+         if (words[i] == 0)
+         {
+             if (cur.base == -1)
+                 cur.base = i, cur.len = 1;
+             else
+                 cur.len++;
+         }
+         else
+         {
+             if (cur.base != -1)
+             {
+                 if (best.base == -1 || cur.len > best.len)
+                     best = cur;
+                 cur.base = -1;
+             }
+         }
+     }
+     if (cur.base != -1)
+     {
+         if (best.base == -1 || cur.len > best.len)
+             best = cur;
+     }
+     if (best.base != -1 && best.len < 2)
+         best.base = -1;
+
+     /*
+      * Format the result.
+      */
+     tp = tmp;
+     for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
+     {
+         /* Are we inside the best run of 0x00's? */
+         if (best.base != -1 && i >= best.base &&
+             i < (best.base + best.len))
+         {
+             if (i == best.base)
+                 *tp++ = ':';
+             continue;
+         }
+         /* Are we following an initial run of 0x00s or any real hex? */
+         if (i != 0)
+             *tp++ = ':';
+         /* Is this address an encapsulated IPv4? */
+         if (i == 6 && best.base == 0 && (best.len == 6 ||
+                                      (best.len == 7 && words[7] != 0x0001) ||
+                                       (best.len == 5 && words[5] == 0xffff)))
+         {
+             int            n;
+
+             n = decoct(src + 12, 4, tp, sizeof tmp - (tp - tmp));
+             if (n == 0)
+             {
+                 errno = EMSGSIZE;
+                 return (NULL);
+             }
+             tp += strlen(tp);
+             break;
+         }
+         tp += SPRINTF((tp, "%x", words[i]));
+     }
+
+     /* Was it a trailing run of 0x00's? */
+     if (best.base != -1 && (best.base + best.len) ==
+         (NS_IN6ADDRSZ / NS_INT16SZ))
+         *tp++ = ':';
+     *tp = '\0';
+
+     if (bits != -1 && bits != 128)
+         tp += SPRINTF((tp, "/%u", bits));
+
+     /*
+      * Check for overflow, copy, and we're done.
+      */
+     if ((size_t) (tp - tmp) > size)
+     {
+         errno = EMSGSIZE;
+         return (NULL);
+     }
+     strcpy(dst, tmp);
+     return (dst);
+ }
+

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Dimitri Fontaine
Дата:
Сообщение: Re: Fwd: What do these terms mean in the SOURCE CODE?
Следующее
От: Jeff Janes
Дата:
Сообщение: Re: Spread checkpoint sync