Tom Lane wrote: > Bruce Momjian <br...@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 <br...@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); + } +
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers