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
Re: duplicate connection failure messages |
| Список | 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 по дате отправления: