From df63503dc2fbe59292a65c685479bf1a439b9b4d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 23 Jul 2003 23:30:41 +0000 Subject: [PATCH] Have a go at fixing various outstanding portability issues in code that was modified for IPv6. Use a robust definition of struct sockaddr_storage, do a proper configure test to see if ss_len exists, don't assume that getnameinfo() will handle AF_UNIX sockets, don't trust getaddrinfo to return the protocol we ask for, etc. This incorporates several outstanding patches from Kurt Roeckx, but I'm to blame for anything that doesn't work ... --- config/c-library.m4 | 24 ++-- configure | 180 ++++++++++++++++++++++++++++ configure.in | 4 +- src/backend/libpq/auth.c | 11 +- src/backend/libpq/hba.c | 55 +++++---- src/backend/libpq/ip.c | 114 ++++++++++++++++-- src/backend/libpq/pqcomm.c | 47 ++++---- src/backend/postmaster/pgstat.c | 33 +++-- src/backend/postmaster/postmaster.c | 141 +++++++++++----------- src/include/getaddrinfo.h | 3 +- src/include/libpq/ip.h | 17 ++- src/include/libpq/pqcomm.h | 61 ++++------ src/include/pg_config.h.in | 12 +- src/interfaces/libpq/fe-connect.c | 64 +++++----- src/port/getaddrinfo.c | 59 ++++----- 15 files changed, 565 insertions(+), 260 deletions(-) diff --git a/config/c-library.m4 b/config/c-library.m4 index d301b0155c..d6acd8c98b 100644 --- a/config/c-library.m4 +++ b/config/c-library.m4 @@ -1,5 +1,5 @@ # Macros that test various C library quirks -# $Header: /cvsroot/pgsql/config/c-library.m4,v 1.22 2003/06/23 23:51:59 momjian Exp $ +# $Header: /cvsroot/pgsql/config/c-library.m4,v 1.23 2003/07/23 23:30:39 tgl Exp $ # PGAC_VAR_INT_TIMEZONE @@ -100,8 +100,8 @@ AC_DEFUN([PGAC_STRUCT_SOCKADDR_UN], # PGAC_STRUCT_SOCKADDR_STORAGE # ---------------------------- -# If `struct sockaddr_storage' exists, define HAVE_STRUCT_SOCKADDR_STORAGE. If -# it is missing then one could define it. +# If `struct sockaddr_storage' exists, define HAVE_STRUCT_SOCKADDR_STORAGE. +# If it is missing then one could define it. AC_DEFUN([PGAC_STRUCT_SOCKADDR_STORAGE], [AC_CHECK_TYPES([struct sockaddr_storage], [], [], [#include @@ -110,18 +110,24 @@ AC_DEFUN([PGAC_STRUCT_SOCKADDR_STORAGE], #endif ])])# PGAC_STRUCT_SOCKADDR_STORAGE -# PGAC_STRUCT_SOCKADDR_STORAGE_SS_FAMILY +# PGAC_STRUCT_SOCKADDR_STORAGE_MEMBERS # -------------------------------------- -# This checks if the struct sockaddr has a proper ss_family and not an -# __ss_family as rfc2553 defined. -AC_DEFUN([PGAC_STRUCT_SOCKADDR_STORAGE_SS_FAMILY], +# Check the members of `struct sockaddr_storage'. We need to know about +# ss_family and ss_len. (Some platforms follow RFC 2553 and call them +# __ss_family and __ss_len.) We also check struct sockaddr's sa_len; +# if we have to define our own `struct sockaddr_storage', this tells us +# whether we need to provide an ss_len field. +AC_DEFUN([PGAC_STRUCT_SOCKADDR_STORAGE_MEMBERS], [AC_CHECK_MEMBERS([struct sockaddr_storage.ss_family, - struct sockaddr_storage.__ss_family], [], [], + struct sockaddr_storage.__ss_family, + struct sockaddr_storage.ss_len, + struct sockaddr_storage.__ss_len, + struct sockaddr.sa_len], [], [], [#include #ifdef HAVE_SYS_SOCKET_H #include #endif -])])# PGAC_STRUCT_SOCKADDR_STORAGE_SS_FAMILY +])])# PGAC_STRUCT_SOCKADDR_STORAGE_MEMBERS # PGAC_STRUCT_ADDRINFO diff --git a/configure b/configure index 99bce0c041..24066b6fac 100755 --- a/configure +++ b/configure @@ -9990,6 +9990,186 @@ cat >>confdefs.h <<_ACEOF _ACEOF +fi +echo "$as_me:$LINENO: checking for struct sockaddr_storage.ss_len" >&5 +echo $ECHO_N "checking for struct sockaddr_storage.ss_len... $ECHO_C" >&6 +if test "${ac_cv_member_struct_sockaddr_storage_ss_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static struct sockaddr_storage ac_aggr; +if (ac_aggr.ss_len) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_sockaddr_storage_ss_len=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_member_struct_sockaddr_storage_ss_len=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_storage_ss_len" >&5 +echo "${ECHO_T}$ac_cv_member_struct_sockaddr_storage_ss_len" >&6 +if test $ac_cv_member_struct_sockaddr_storage_ss_len = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1 +_ACEOF + + +fi +echo "$as_me:$LINENO: checking for struct sockaddr_storage.__ss_len" >&5 +echo $ECHO_N "checking for struct sockaddr_storage.__ss_len... $ECHO_C" >&6 +if test "${ac_cv_member_struct_sockaddr_storage___ss_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static struct sockaddr_storage ac_aggr; +if (ac_aggr.__ss_len) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_sockaddr_storage___ss_len=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_member_struct_sockaddr_storage___ss_len=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_storage___ss_len" >&5 +echo "${ECHO_T}$ac_cv_member_struct_sockaddr_storage___ss_len" >&6 +if test $ac_cv_member_struct_sockaddr_storage___ss_len = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN 1 +_ACEOF + + +fi +echo "$as_me:$LINENO: checking for struct sockaddr.sa_len" >&5 +echo $ECHO_N "checking for struct sockaddr.sa_len... $ECHO_C" >&6 +if test "${ac_cv_member_struct_sockaddr_sa_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static struct sockaddr ac_aggr; +if (ac_aggr.sa_len) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_sockaddr_sa_len=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_member_struct_sockaddr_sa_len=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_sa_len" >&5 +echo "${ECHO_T}$ac_cv_member_struct_sockaddr_sa_len" >&6 +if test $ac_cv_member_struct_sockaddr_sa_len = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_SA_LEN 1 +_ACEOF + + fi echo "$as_me:$LINENO: checking for struct addrinfo" >&5 diff --git a/configure.in b/configure.in index 515d53c183..d189a5ffdb 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -dnl $Header: /cvsroot/pgsql/configure.in,v 1.269 2003/07/23 17:27:28 momjian Exp $ +dnl $Header: /cvsroot/pgsql/configure.in,v 1.270 2003/07/23 23:30:40 tgl Exp $ dnl dnl Developers, please strive to achieve this order: dnl @@ -778,7 +778,7 @@ PGAC_STRUCT_TIMEZONE PGAC_UNION_SEMUN PGAC_STRUCT_SOCKADDR_UN PGAC_STRUCT_SOCKADDR_STORAGE -PGAC_STRUCT_SOCKADDR_STORAGE_SS_FAMILY +PGAC_STRUCT_SOCKADDR_STORAGE_MEMBERS PGAC_STRUCT_ADDRINFO AC_CHECK_TYPES([struct cmsgcred, struct fcred, struct sockcred], [], [], diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index ca6bfcf4d7..a24f097846 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.104 2003/07/22 19:00:10 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.105 2003/07/23 23:30:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -434,11 +434,10 @@ ClientAuthentication(Port *port) { char hostinfo[NI_MAXHOST]; - getnameinfo((struct sockaddr *) &port->raddr.addr, - port->raddr.salen, - hostinfo, sizeof(hostinfo), - NULL, 0, - NI_NUMERICHOST); + getnameinfo_all(&port->raddr.addr, port->raddr.salen, + hostinfo, sizeof(hostinfo), + NULL, 0, + NI_NUMERICHOST); ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index f0bd0b8515..0d98e729a4 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.106 2003/07/22 21:19:22 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.107 2003/07/23 23:30:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -648,31 +648,33 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) hints.ai_next = NULL; /* Get the IP address either way */ - ret = getaddrinfo2(token, NULL, &hints, &file_ip_addr); + ret = getaddrinfo_all(token, NULL, &hints, &file_ip_addr); if (ret || !file_ip_addr) { ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("failed to interpret IP address \"%s\" in config file: %s", + errmsg("could not interpret IP address \"%s\" in config file: %s", token, gai_strerror(ret)))); if (cidr_slash) *cidr_slash = '/'; goto hba_syntax; } + if (cidr_slash) + *cidr_slash = '/'; + if (file_ip_addr->ai_family != port->raddr.addr.ss_family) { /* Wrong address family. */ - freeaddrinfo2(hints.ai_family, file_ip_addr); + freeaddrinfo_all(hints.ai_family, file_ip_addr); return; } /* Get the netmask */ if (cidr_slash) { - *cidr_slash = '/'; if (SockAddr_cidr_mask(&mask, cidr_slash + 1, - file_ip_addr->ai_family) < 0) + file_ip_addr->ai_family) < 0) goto hba_syntax; } else @@ -683,13 +685,13 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) goto hba_syntax; token = lfirst(line); - ret = getaddrinfo2(token, NULL, &hints, &file_ip_mask); + ret = getaddrinfo_all(token, NULL, &hints, &file_ip_mask); if (ret || !file_ip_mask) goto hba_syntax; mask = (struct sockaddr_storage *)file_ip_mask->ai_addr; - if(file_ip_addr->ai_family != mask->ss_family) + if (file_ip_addr->ai_family != mask->ss_family) goto hba_syntax; } @@ -703,12 +705,13 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) /* Must meet network restrictions */ if (!rangeSockAddr(&port->raddr.addr, - (struct sockaddr_storage *)file_ip_addr->ai_addr, mask)) + (struct sockaddr_storage *)file_ip_addr->ai_addr, + mask)) goto hba_freeaddr; - freeaddrinfo2(hints.ai_family, file_ip_addr); + freeaddrinfo_all(hints.ai_family, file_ip_addr); if (file_ip_mask) - freeaddrinfo2(hints.ai_family, file_ip_mask); + freeaddrinfo_all(hints.ai_family, file_ip_mask); } else goto hba_syntax; @@ -731,16 +734,16 @@ hba_syntax: else ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("missing entry in pg_hba.conf file at end of line %d", + errmsg("missing field in pg_hba.conf file at end of line %d", line_number))); *error_p = true; hba_freeaddr: if (file_ip_addr) - freeaddrinfo2(hints.ai_family, file_ip_addr); + freeaddrinfo_all(hints.ai_family, file_ip_addr); if (file_ip_mask) - freeaddrinfo2(hints.ai_family, file_ip_mask); + freeaddrinfo_all(hints.ai_family, file_ip_mask); } @@ -1209,14 +1212,14 @@ ident_inet(const SockAddr remote_addr, * Might look a little weird to first convert it to text and * then back to sockaddr, but it's protocol independent. */ - getnameinfo((struct sockaddr *)&remote_addr.addr, remote_addr.salen, - remote_addr_s, sizeof(remote_addr_s), - remote_port, sizeof(remote_port), - NI_NUMERICHOST | NI_NUMERICSERV); - getnameinfo((struct sockaddr *)&local_addr.addr, local_addr.salen, - local_addr_s, sizeof(local_addr_s), - local_port, sizeof(local_port), - NI_NUMERICHOST | NI_NUMERICSERV); + getnameinfo_all(&remote_addr.addr, remote_addr.salen, + remote_addr_s, sizeof(remote_addr_s), + remote_port, sizeof(remote_port), + NI_NUMERICHOST | NI_NUMERICSERV); + getnameinfo_all(&local_addr.addr, local_addr.salen, + local_addr_s, sizeof(local_addr_s), + local_port, sizeof(local_port), + NI_NUMERICHOST | NI_NUMERICSERV); snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT); hints.ai_flags = AI_NUMERICHOST; @@ -1227,7 +1230,7 @@ ident_inet(const SockAddr remote_addr, hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; - rc = getaddrinfo2(remote_addr_s, ident_port, &hints, &ident_serv); + rc = getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv); if (rc || !ident_serv) return false; /* we don't expect this to happen */ @@ -1239,7 +1242,7 @@ ident_inet(const SockAddr remote_addr, hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; - rc = getaddrinfo2(local_addr_s, NULL, &hints, &la); + rc = getaddrinfo_all(local_addr_s, NULL, &hints, &la); if (rc || !la) return false; /* we don't expect this to happen */ @@ -1323,8 +1326,8 @@ ident_inet(const SockAddr remote_addr, ident_inet_done: if (sock_fd >= 0) closesocket(sock_fd); - freeaddrinfo2(remote_addr.addr.ss_family, ident_serv); - freeaddrinfo2(local_addr.addr.ss_family, la); + freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv); + freeaddrinfo_all(local_addr.addr.ss_family, la); return ident_return; } diff --git a/src/backend/libpq/ip.c b/src/backend/libpq/ip.c index 091b381ec1..c5a0a485ef 100644 --- a/src/backend/libpq/ip.c +++ b/src/backend/libpq/ip.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.15 2003/06/12 08:15:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.16 2003/07/23 23:30:40 tgl Exp $ * * This file and the IPV6 implementation were initially provided by * Nigel Kukard , Linux Based Systems Design @@ -53,15 +53,20 @@ static int rangeSockAddrAF_INET6(const struct sockaddr_in6 *addr, static int getaddrinfo_unix(const char *path, const struct addrinfo *hintsp, struct addrinfo **result); + +static int getnameinfo_unix(const struct sockaddr_un *sa, int salen, + char *node, int nodelen, + char *service, int servicelen, + int flags); #endif /* - * getaddrinfo2 - get address info for Unix, IPv4 and IPv6 sockets + * getaddrinfo_all - get address info for Unix, IPv4 and IPv6 sockets */ int -getaddrinfo2(const char *hostname, const char *servname, - const struct addrinfo *hintp, struct addrinfo **result) +getaddrinfo_all(const char *hostname, const char *servname, + const struct addrinfo *hintp, struct addrinfo **result) { #ifdef HAVE_UNIX_SOCKETS if (hintp != NULL && hintp->ai_family == AF_UNIX) @@ -75,7 +80,7 @@ getaddrinfo2(const char *hostname, const char *servname, /* - * freeaddrinfo2 - free addrinfo structures for IPv4, IPv6, or Unix + * freeaddrinfo_all - free addrinfo structures for IPv4, IPv6, or Unix * * Note: the ai_family field of the original hint structure must be passed * so that we can tell whether the addrinfo struct was built by the system's @@ -84,12 +89,12 @@ getaddrinfo2(const char *hostname, const char *servname, * not safe to look at ai_family in the addrinfo itself. */ void -freeaddrinfo2(int hint_ai_family, struct addrinfo *ai) +freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai) { #ifdef HAVE_UNIX_SOCKETS if (hint_ai_family == AF_UNIX) { - /* struct was built by getaddrinfo_unix (see getaddrinfo2) */ + /* struct was built by getaddrinfo_unix (see getaddrinfo_all) */ while (ai != NULL) { struct addrinfo *p = ai; @@ -109,11 +114,53 @@ freeaddrinfo2(int hint_ai_family, struct addrinfo *ai) } +/* + * getnameinfo_all - get name info for Unix, IPv4 and IPv6 sockets + * + * The API of this routine differs from the standard getnameinfo() definition + * in two ways: first, the addr parameter is declared as sockaddr_storage + * rather than struct sockaddr, and second, the node and service fields are + * guaranteed to be filled with something even on failure return. + */ +int +getnameinfo_all(const struct sockaddr_storage *addr, int salen, + char *node, int nodelen, + char *service, int servicelen, + int flags) +{ + int rc; + +#ifdef HAVE_UNIX_SOCKETS + if (addr && addr->ss_family == AF_UNIX) + rc = getnameinfo_unix((const struct sockaddr_un *) addr, salen, + node, nodelen, + service, servicelen, + flags); + else +#endif + rc = getnameinfo((const struct sockaddr *) addr, salen, + node, nodelen, + service, servicelen, + flags); + + if (rc != 0) + { + if (node) + StrNCpy(node, "???", nodelen); + if (service) + StrNCpy(service, "???", servicelen); + } + + return rc; +} + + #if defined(HAVE_UNIX_SOCKETS) + /* ------- * getaddrinfo_unix - get unix socket info using IPv6-compatible API * - * Bug: only one addrinfo is set even though hintsp is NULL or + * Bugs: only one addrinfo is set even though hintsp is NULL or * ai_socktype is 0 * AI_CANONNAME is not supported. * ------- @@ -176,12 +223,59 @@ getaddrinfo_unix(const char *path, const struct addrinfo *hintsp, strcpy(unp->sun_path, path); -#if SALEN +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN unp->sun_len = sizeof(struct sockaddr_un); -#endif /* SALEN */ +#endif + + return 0; +} + +/* + * Convert an address to a hostname. + */ +static int +getnameinfo_unix(const struct sockaddr_un *sa, int salen, + char *node, int nodelen, + char *service, int servicelen, + int flags) +{ + int ret = -1; + + /* Invalid arguments. */ + if (sa == NULL || sa->sun_family != AF_UNIX || + (node == NULL && service == NULL)) + { + return EAI_FAIL; + } + + /* We don't support those. */ + if ((node && !(flags & NI_NUMERICHOST)) + || (service && !(flags & NI_NUMERICSERV))) + { + return EAI_FAIL; + } + + if (node) + { + ret = snprintf(node, nodelen, "%s", "localhost"); + if (ret == -1 || ret > nodelen) + { + return EAI_MEMORY; + } + } + + if (service) + { + ret = snprintf(service, servicelen, "%s", sa->sun_path); + if (ret == -1 || ret > servicelen) + { + return EAI_MEMORY; + } + } return 0; } + #endif /* HAVE_UNIX_SOCKETS */ diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 7f3013925a..7cd9e23f32 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -30,7 +30,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.158 2003/07/22 19:00:10 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.159 2003/07/23 23:30:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -190,16 +190,18 @@ StreamDoUnlink(void) #endif /* HAVE_UNIX_SOCKETS */ /* - * StreamServerPort -- open a sock stream "listening" port. + * StreamServerPort -- open a "listening" port to accept connections. * - * This initializes the Postmaster's connection-accepting port *fdP. + * Successfully opened sockets are added to the ListenSocket[] array, + * at the first position that isn't -1. * * RETURNS: STATUS_OK or STATUS_ERROR */ int StreamServerPort(int family, char *hostName, unsigned short portNumber, - char *unixSocketName, int ListenSocket[], int MaxListen) + char *unixSocketName, + int ListenSocket[], int MaxListen) { int fd, err; @@ -216,7 +218,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, /* Initialize hint structure */ MemSet(&hint, 0, sizeof(hint)); hint.ai_family = family; - hint.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + hint.ai_flags = AI_PASSIVE; hint.ai_socktype = SOCK_STREAM; #ifdef HAVE_UNIX_SOCKETS @@ -234,13 +236,18 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, service = portNumberStr; } - ret = getaddrinfo2(hostName, service, &hint, &addrs); - if (ret || addrs == NULL) + ret = getaddrinfo_all(hostName, service, &hint, &addrs); + if (ret || !addrs) { - ereport(LOG, - (errmsg("failed to translate hostname to address: %s", - gai_strerror(ret)))); - freeaddrinfo2(hint.ai_family, addrs); + if (hostName) + ereport(LOG, + (errmsg("could not translate hostname \"%s\", service \"%s\" to address: %s", + hostName, service, gai_strerror(ret)))); + else + ereport(LOG, + (errmsg("could not translate service \"%s\" to address: %s", + service, gai_strerror(ret)))); + freeaddrinfo_all(hint.ai_family, addrs); return STATUS_ERROR; } @@ -250,7 +257,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, { /* Only set up a unix domain socket when * they really asked for it. The service/port - * is different in that case. */ + * is different in that case. + */ continue; } @@ -258,17 +266,15 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, for (; listen_index < MaxListen; listen_index++) { if (ListenSocket[listen_index] == -1) - { break; - } } - if (listen_index == MaxListen) + if (listen_index >= MaxListen) { /* Nothing found. */ break; } - if ((fd = socket(addr->ai_family, addr->ai_socktype, - addr->ai_protocol)) < 0) + + if ((fd = socket(addr->ai_family, SOCK_STREAM, 0)) < 0) { ereport(LOG, (errcode_for_socket_access(), @@ -276,8 +282,6 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, continue; } - - if (!IS_AF_UNIX(addr->ai_family)) { if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, @@ -363,12 +367,11 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, added++; } - freeaddrinfo(addrs); + freeaddrinfo_all(hint.ai_family, addrs); if (!added) - { return STATUS_ERROR; - } + return STATUS_OK; } diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 5ed1247e95..f8882737ee 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -13,7 +13,7 @@ * * Copyright (c) 2001-2003, PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.39 2003/07/22 19:13:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.40 2003/07/23 23:30:40 tgl Exp $ * ---------- */ #include "postgres.h" @@ -147,7 +147,7 @@ void pgstat_init(void) { ACCEPT_TYPE_ARG3 alen; - struct addrinfo *addr = NULL, hints; + struct addrinfo *addrs = NULL, *addr, hints; int ret; /* @@ -189,17 +189,27 @@ pgstat_init(void) hints.ai_addr = NULL; hints.ai_canonname = NULL; hints.ai_next = NULL; - ret = getaddrinfo2("localhost", NULL, &hints, &addr); - if (ret || !addr) + ret = getaddrinfo_all("localhost", NULL, &hints, &addrs); + if (ret || !addrs) { ereport(LOG, - (errmsg("getaddrinfo2(\"localhost\") failed: %s", + (errmsg("could not resolve \"localhost\": %s", gai_strerror(ret)))); goto startup_failed; } - if ((pgStatSock = socket(addr->ai_family, - addr->ai_socktype, addr->ai_protocol)) < 0) + for (addr = addrs; addr; addr = addr->ai_next) + { +#ifdef HAVE_UNIX_SOCKETS + /* Ignore AF_UNIX sockets, if any are returned. */ + if (addr->ai_family == AF_UNIX) + continue; +#endif + if ((pgStatSock = socket(addr->ai_family, SOCK_DGRAM, 0)) >= 0) + break; + } + + if (!addr || pgStatSock < 0) { ereport(LOG, (errcode_for_socket_access(), @@ -218,8 +228,9 @@ pgstat_init(void) errmsg("could not bind socket for statistics: %m"))); goto startup_failed; } - freeaddrinfo2(hints.ai_family, addr); - addr = NULL; + + freeaddrinfo_all(hints.ai_family, addrs); + addrs = NULL; alen = sizeof(pgStatAddr); if (getsockname(pgStatSock, (struct sockaddr *)&pgStatAddr, &alen) < 0) @@ -272,8 +283,8 @@ pgstat_init(void) return; startup_failed: - if (addr) - freeaddrinfo2(hints.ai_family, addr); + if (addrs) + freeaddrinfo_all(hints.ai_family, addrs); if (pgStatSock >= 0) closesocket(pgStatSock); diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 614c76e64e..fb64781bf8 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.335 2003/07/22 20:29:13 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.336 2003/07/23 23:30:40 tgl Exp $ * * NOTES * @@ -168,9 +168,9 @@ int ReservedBackends; static char *progname = (char *) NULL; -/* The sockets we're listening to. */ +/* The socket(s) we're listening to. */ #define MAXLISTEN 10 -int ListenSocket[MAXLISTEN]; +static int ListenSocket[MAXLISTEN]; /* Used to reduce macros tests */ #ifdef EXEC_BACKEND @@ -277,7 +277,7 @@ static int ServerLoop(void); static int BackendStartup(Port *port); static int ProcessStartupPacket(Port *port, bool SSLdone); static void processCancelRequest(Port *port, void *pkt); -static int initMasks(fd_set *rmask, fd_set *wmask); +static int initMasks(fd_set *rmask); static void report_fork_failure_to_client(Port *port, int errnum); enum CAC_state { @@ -727,73 +727,80 @@ PostmasterMain(int argc, char *argv[]) * Establish input sockets. */ for (i = 0; i < MAXLISTEN; i++) - { ListenSocket[i] = -1; - } + if (NetServer) { if (VirtualHost && VirtualHost[0]) { - char *p, *q; + char *curhost, *endptr; char c = 0; - q = VirtualHost; - do + curhost = VirtualHost; + for (;;) { - p = strchr(q, ' '); - if (p) + while (*curhost == ' ') /* skip any extra spaces */ + curhost++; + if (*curhost == '\0') + break; + endptr = strchr(curhost, ' '); + if (endptr) { - c = *p; - *p = '\0'; + c = *endptr; + *endptr = '\0'; } - status = StreamServerPort(AF_UNSPEC, q, - (unsigned short) PostPortNumber, - UnixSocketDir, ListenSocket, MAXLISTEN); + status = StreamServerPort(AF_UNSPEC, curhost, + (unsigned short) PostPortNumber, + UnixSocketDir, + ListenSocket, MAXLISTEN); if (status != STATUS_OK) { - postmaster_error("cannot create tcpip " - "listen socket for: %s", p); + postmaster_error("could not create listen socket for \"%s\"", + curhost); } - if (p) + if (endptr) { - *p = c; - q = p + 1; + *endptr = c; + curhost = endptr + 1; } + else + break; } - while (p); } else { status = StreamServerPort(AF_UNSPEC, NULL, - (unsigned short) PostPortNumber, - UnixSocketDir, ListenSocket, MAXLISTEN); + (unsigned short) PostPortNumber, + UnixSocketDir, + ListenSocket, MAXLISTEN); if (status != STATUS_OK) { - postmaster_error("cannot create tcpip listen " - "socket."); + postmaster_error("could not create TCP/IP listen socket"); } } + #ifdef USE_RENDEZVOUS - if (rendezvous_name != NULL) - { - DNSServiceRegistrationCreate(rendezvous_name, - "_postgresql._tcp.", - "", - htonl(PostPortNumber), - "", - (DNSServiceRegistrationReply)reg_reply, - NULL); - } + if (rendezvous_name != NULL) + { + DNSServiceRegistrationCreate(rendezvous_name, + "_postgresql._tcp.", + "", + htonl(PostPortNumber), + "", + (DNSServiceRegistrationReply)reg_reply, + NULL); + } #endif } #ifdef HAVE_UNIX_SOCKETS status = StreamServerPort(AF_UNIX, NULL, - (unsigned short) PostPortNumber, - UnixSocketDir, ListenSocket, MAXLISTEN); + (unsigned short) PostPortNumber, + UnixSocketDir, + ListenSocket, MAXLISTEN); if (status != STATUS_OK) { - postmaster_error("cannot create UNIX stream port"); + postmaster_error("could not create UNIX stream port"); ExitPostmaster(1); } #endif @@ -994,7 +1001,7 @@ usage(const char *progname) static int ServerLoop(void) { - fd_set readmask, writemask; + fd_set readmask; int nSockets; struct timeval now, later; struct timezone tz; @@ -1002,13 +1009,12 @@ ServerLoop(void) gettimeofday(&now, &tz); - nSockets = initMasks(&readmask, &writemask); + nSockets = initMasks(&readmask); for (;;) { Port *port; - fd_set rmask, - wmask; + fd_set rmask; struct timeval timeout; /* @@ -1057,11 +1063,11 @@ ServerLoop(void) * Wait for something to happen. */ memcpy((char *) &rmask, (char *) &readmask, sizeof(fd_set)); - memcpy((char *) &wmask, (char *) &writemask, sizeof(fd_set)); PG_SETMASK(&UnBlockSig); - if (select(nSockets, &rmask, &wmask, (fd_set *) NULL, &timeout) < 0) + if (select(nSockets, &rmask, (fd_set *) NULL, + (fd_set *) NULL, &timeout) < 0) { PG_SETMASK(&BlockSig); if (errno == EINTR || errno == EWOULDBLOCK) @@ -1096,12 +1102,14 @@ ServerLoop(void) } /* - * New connection pending on our well-known port's socket? If so, + * New connection pending on any of our sockets? If so, * fork a child process to deal with it. */ for (i = 0; i < MAXLISTEN; i++) { - if (ListenSocket[i] != -1 && FD_ISSET(ListenSocket[i], &rmask)) + if (ListenSocket[i] == -1) + break; + if (FD_ISSET(ListenSocket[i], &rmask)) { port = ConnCreate(ListenSocket[i]); if (port) @@ -1126,28 +1134,27 @@ ServerLoop(void) /* - * Initialise the read and write masks for select() for the well-known ports + * Initialise the masks for select() for the ports * we are listening on. Return the number of sockets to listen on. */ static int -initMasks(fd_set *rmask, fd_set *wmask) +initMasks(fd_set *rmask) { int nsocks = -1; int i; FD_ZERO(rmask); - FD_ZERO(wmask); for (i = 0; i < MAXLISTEN; i++) { int fd = ListenSocket[i]; - if (fd != -1) - { - FD_SET(fd, rmask); - if (fd > nsocks) - nsocks = fd; - } + + if (fd == -1) + break; + FD_SET(fd, rmask); + if (fd > nsocks) + nsocks = fd; } return nsocks + 1; @@ -2352,17 +2359,15 @@ BackendFork(Port *port) */ remote_host[0] = '\0'; remote_port[0] = '\0'; - if (!getnameinfo((struct sockaddr *)&port->raddr.addr, - port->raddr.salen, - remote_host, sizeof(remote_host), - remote_port, sizeof(remote_host), - (log_hostname ? 0 : NI_NUMERICHOST) | NI_NUMERICSERV)) - { - getnameinfo((struct sockaddr *)&port->raddr.addr, - port->raddr.salen, - remote_host, sizeof(remote_host), - remote_port, sizeof(remote_host), - NI_NUMERICHOST | NI_NUMERICSERV); + if (getnameinfo_all(&port->raddr.addr, port->raddr.salen, + remote_host, sizeof(remote_host), + remote_port, sizeof(remote_port), + (log_hostname ? 0 : NI_NUMERICHOST) | NI_NUMERICSERV)) + { + getnameinfo_all(&port->raddr.addr, port->raddr.salen, + remote_host, sizeof(remote_host), + remote_port, sizeof(remote_port), + NI_NUMERICHOST | NI_NUMERICSERV); } if (Log_connections) @@ -2373,7 +2378,7 @@ BackendFork(Port *port) if (LogSourcePort) { /* modify remote_host for use in ps status */ - char tmphost[sizeof(remote_host) + 10]; + char tmphost[NI_MAXHOST]; snprintf(tmphost, sizeof(tmphost), "%s:%s", remote_host, remote_port); StrNCpy(remote_host, tmphost, sizeof(remote_host)); diff --git a/src/include/getaddrinfo.h b/src/include/getaddrinfo.h index ced6df07e9..6312482a7a 100644 --- a/src/include/getaddrinfo.h +++ b/src/include/getaddrinfo.h @@ -3,7 +3,6 @@ * getaddrinfo.h * Support getaddrinfo() on platforms that don't have it. * - * * Note: we use our own routines on platforms that don't HAVE_STRUCT_ADDRINFO, * whether or not the library routine getaddrinfo() can be found. This * policy is needed because on some platforms a manually installed libbind.a @@ -16,7 +15,7 @@ * * Copyright (c) 2003, PostgreSQL Global Development Group * - * $Id: getaddrinfo.h,v 1.6 2003/06/12 08:15:29 momjian Exp $ + * $Id: getaddrinfo.h,v 1.7 2003/07/23 23:30:40 tgl Exp $ * *------------------------------------------------------------------------- */ diff --git a/src/include/libpq/ip.h b/src/include/libpq/ip.h index b770d33bfe..5c614b1681 100644 --- a/src/include/libpq/ip.h +++ b/src/include/libpq/ip.h @@ -5,7 +5,7 @@ * * Copyright (c) 2003, PostgreSQL Global Development Group * - * $Id: ip.h,v 1.8 2003/06/12 07:36:51 momjian Exp $ + * $Id: ip.h,v 1.9 2003/07/23 23:30:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,10 +16,15 @@ #include "libpq/pqcomm.h" -extern int getaddrinfo2(const char *hostname, const char *servname, - const struct addrinfo *hintp, - struct addrinfo **result); -extern void freeaddrinfo2(int hint_ai_family, struct addrinfo *ai); +extern int getaddrinfo_all(const char *hostname, const char *servname, + const struct addrinfo *hintp, + struct addrinfo **result); +extern void freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai); + +extern int getnameinfo_all(const struct sockaddr_storage *addr, int salen, + char *node, int nodelen, + char *service, int servicelen, + int flags); extern int rangeSockAddr(const struct sockaddr_storage *addr, const struct sockaddr_storage *netaddr, @@ -29,7 +34,7 @@ extern int SockAddr_cidr_mask(struct sockaddr_storage **mask, char *numbits, int family); #ifdef HAVE_UNIX_SOCKETS -#define IS_AF_UNIX(fam) (fam == AF_UNIX) +#define IS_AF_UNIX(fam) ((fam) == AF_UNIX) #else #define IS_AF_UNIX(fam) (0) #endif diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h index 0cabdc24c1..caa186b832 100644 --- a/src/include/libpq/pqcomm.h +++ b/src/include/libpq/pqcomm.h @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pqcomm.h,v 1.89 2003/07/15 17:54:34 tgl Exp $ + * $Id: pqcomm.h,v 1.90 2003/07/23 23:30:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -32,56 +32,47 @@ #include #endif /* not WIN32 */ -#ifndef HAVE_STRUCT_SOCKADDR_STORAGE -/* Define a struct sockaddr_storage if we don't have one. */ - -#define _SS_MAXSIZE 128 /* Implementation specific max size */ +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE -#ifdef __CYGWIN__ -typedef unsigned short sa_family_t; +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY +# ifdef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY +# define ss_family __ss_family +# else +# error struct sockaddr_storage does not provide an ss_family member +# endif #endif -/* This must exactly match the non-padding fields of sockaddr_storage! */ -struct nopad_sockaddr_storage { -#ifdef SALEN - uint8 __ss_len; /* address length */ +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN +#define ss_len __ss_len +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1 #endif - sa_family_t ss_family; /* address family */ - - int64 __ss_align; /* ensures struct is properly aligned */ -}; -struct sockaddr_storage { -#ifdef SALEN - uint8 __ss_len; /* address length */ -#endif - sa_family_t ss_family; /* address family */ +#else /* !HAVE_STRUCT_SOCKADDR_STORAGE */ - int64 __ss_align; /* ensures struct is properly aligned */ +/* Define a struct sockaddr_storage if we don't have one. */ - char __ss_pad[_SS_MAXSIZE - sizeof(struct nopad_sockaddr_storage)]; - /* ensures struct has desired size */ +struct sockaddr_storage { + union { + struct sockaddr sa; /* get the system-dependent fields */ + int64 ss_align; /* ensures struct is properly aligned */ + char ss_pad[128]; /* ensures struct has desired size */ + } ss_stuff; }; -#elif !defined(HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY) -# ifdef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY -# define ss_family __ss_family -# else -# error struct sockaddr_storage does not provide an ss_family member -# endif +#define ss_family ss_stuff.sa.sa_family +/* It should have an ss_len field if sockaddr has sa_len. */ +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN +#define ss_len ss_stuff.sa.sa_len +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1 #endif +#endif /* HAVE_STRUCT_SOCKADDR_STORAGE */ + typedef struct { struct sockaddr_storage addr; ACCEPT_TYPE_ARG3 salen; } SockAddr; -/* Some systems don't have it, so default it to 0 so it doesn't - * have any effect on those systems. */ -#ifndef AI_ADDRCONFIG -#define AI_ADDRCONFIG 0 -#endif - /* Configure the UNIX socket location for the well known port. */ #define UNIXSOCK_PATH(path,port,defpath) \ diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 41806fe8fb..2fe4cd3ea1 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -420,15 +420,24 @@ /* Define to 1 if the system has the type `struct fcred'. */ #undef HAVE_STRUCT_FCRED +/* Define to 1 if `sa_len' is member of `struct sockaddr'. */ +#undef HAVE_STRUCT_SOCKADDR_SA_LEN + /* Define to 1 if the system has the type `struct sockaddr_storage'. */ #undef HAVE_STRUCT_SOCKADDR_STORAGE /* Define to 1 if `ss_family' is member of `struct sockaddr_storage'. */ #undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY +/* Define to 1 if `ss_len' is member of `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN + /* Define to 1 if `__ss_family' is member of `struct sockaddr_storage'. */ #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY +/* Define to 1 if `__ss_len' is member of `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN + /* Define to 1 if the system has the type `struct sockaddr_un'. */ #undef HAVE_STRUCT_SOCKADDR_UN @@ -594,7 +603,8 @@ /* Define to select SysV-style shared memory. */ #undef USE_SYSV_SHARED_MEMORY -/* Define to 1 to build libpq and ecpg to be thread-safe. (--with-threads) */ +/* Define to 1 to build libpq and ecpg to be thread-safe. + (--enable-thread-safeness) */ #undef USE_THREADS /* Define to select unnamed POSIX semaphores. */ diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index a931fe9fa2..0518cd21b4 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.252 2003/06/23 19:20:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.253 2003/07/23 23:30:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -759,26 +759,33 @@ connectNoDelay(PGconn *conn) static void connectFailureMessage(PGconn *conn, int errorno) { - char hostname[NI_MAXHOST]; - char service[NI_MAXHOST]; char sebuf[256]; - getnameinfo((struct sockaddr *)&conn->raddr.addr, conn->raddr.salen, - hostname, sizeof(hostname), service, sizeof(service), - NI_NUMERICHOST | NI_NUMERICSERV); - if (conn->raddr.addr.ss_family == AF_UNIX) +#ifdef HAVE_UNIX_SOCKETS + if (IS_AF_UNIX(conn->raddr.addr.ss_family)) + { + char service[NI_MAXHOST]; + + getnameinfo_all(&conn->raddr.addr, conn->raddr.salen, + NULL, 0, + service, sizeof(service), + NI_NUMERICSERV); printfPQExpBuffer(&conn->errorMessage, libpq_gettext( "could not connect to server: %s\n" "\tIs the server running locally and accepting\n" "\tconnections on Unix domain socket \"%s\"?\n" ), - SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)), service); + SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)), + service); + } else +#endif /* HAVE_UNIX_SOCKETS */ + { printfPQExpBuffer(&conn->errorMessage, libpq_gettext( "could not connect to server: %s\n" - "\tIs the server running on host %s and accepting\n" + "\tIs the server running on host \"%s\" and accepting\n" "\tTCP/IP connections on port %s?\n" ), SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)), @@ -788,6 +795,7 @@ connectFailureMessage(PGconn *conn, int errorno) ? conn->pghost : "???"), conn->pgport); + } } @@ -802,7 +810,7 @@ static int connectDBStart(PGconn *conn) { int portnum; - char portstr[64]; + char portstr[128]; struct addrinfo *addrs = NULL; struct addrinfo hint; const char *node = NULL; @@ -816,7 +824,7 @@ connectDBStart(PGconn *conn) conn->outCount = 0; /* - * Determine the parameters to pass to getaddrinfo2. + * Determine the parameters to pass to getaddrinfo_all. */ /* Initialize hint structure */ @@ -854,14 +862,19 @@ connectDBStart(PGconn *conn) } #endif /* HAVE_UNIX_SOCKETS */ - /* Use getaddrinfo2() to resolve the address */ - ret = getaddrinfo2(node, portstr, &hint, &addrs); - if (ret || addrs == NULL) + /* Use getaddrinfo_all() to resolve the address */ + ret = getaddrinfo_all(node, portstr, &hint, &addrs); + if (ret || !addrs) { - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("getaddrinfo() failed: %s\n"), - gai_strerror(ret)); - freeaddrinfo2(hint.ai_family, addrs); + if (node) + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("could not translate hostname \"%s\" to address: %s\n"), + node, gai_strerror(ret)); + else + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("could not translate local service to address: %s\n"), + gai_strerror(ret)); + freeaddrinfo_all(hint.ai_family, addrs); goto connect_errReturn; } @@ -1068,7 +1081,7 @@ keep_going: /* We will come back to here until there { /* * Try to initiate a connection to one of the addresses - * returned by getaddrinfo2(). conn->addr_cur is the + * returned by getaddrinfo_all(). conn->addr_cur is the * next one to try. We fail when we run out of addresses * (reporting the error returned for the *last* alternative, * which may not be what users expect :-(). @@ -1083,9 +1096,7 @@ keep_going: /* We will come back to here until there conn->raddr.salen = addr_cur->ai_addrlen; /* Open a socket */ - conn->sock = socket(addr_cur->ai_family, - addr_cur->ai_socktype, - addr_cur->ai_protocol); + conn->sock = socket(addr_cur->ai_family, SOCK_STREAM, 0); if (conn->sock < 0) { /* @@ -1263,15 +1274,12 @@ retry_connect: * If SSL is enabled and we haven't already got it running, * request it instead of sending the startup message. */ - -#ifdef HAVE_UNIX_SOCKETS - if (conn->raddr.addr.ss_family == AF_UNIX) + if (IS_AF_UNIX(conn->raddr.addr.ss_family)) { /* Don't bother requesting SSL over a Unix socket */ conn->allow_ssl_try = false; conn->require_ssl = false; } -#endif if (conn->allow_ssl_try && conn->ssl == NULL) { ProtocolVersion pv; @@ -1712,7 +1720,7 @@ retry_ssl_read: } /* We can release the address list now. */ - freeaddrinfo2(conn->addrlist_family, conn->addrlist); + freeaddrinfo_all(conn->addrlist_family, conn->addrlist); conn->addrlist = NULL; conn->addr_cur = NULL; @@ -1886,7 +1894,7 @@ freePGconn(PGconn *conn) /* Note that conn->Pfdebug is not ours to close or free */ if (conn->notifyList) DLFreeList(conn->notifyList); - freeaddrinfo2(conn->addrlist_family, conn->addrlist); + freeaddrinfo_all(conn->addrlist_family, conn->addrlist); if (conn->lobjfuncs) free(conn->lobjfuncs); if (conn->inBuffer) diff --git a/src/port/getaddrinfo.c b/src/port/getaddrinfo.c index cc584a2209..011437bb9b 100644 --- a/src/port/getaddrinfo.c +++ b/src/port/getaddrinfo.c @@ -3,12 +3,16 @@ * getaddrinfo.c * Support getaddrinfo() on platforms that don't have it. * + * We also supply getnameinfo() here, assuming that the platform will have + * it if and only if it has getaddrinfo(). If this proves false on some + * platform, we'll need to split this file and provide a separate configure + * test for getnameinfo(). * - * Copyright (c) 2003, PostgreSQL Global Development Group * + * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/port/getaddrinfo.c,v 1.9 2003/06/23 23:52:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/port/getaddrinfo.c,v 1.10 2003/07/23 23:30:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,9 +26,6 @@ #include #include #include -#ifdef HAVE_UNIX_SOCKETS -#include -#endif #endif #include "getaddrinfo.h" @@ -124,8 +125,9 @@ getaddrinfo(const char *node, const char *service, if (service) sin.sin_port = htons((unsigned short) atoi(service)); -#if SALEN - sin.sin_len = sizeof(sin); + +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN + sin.sin_len = sizeof(sin); #endif ai = malloc(sizeof(*ai)); @@ -209,7 +211,7 @@ gai_strerror(int errcode) } /* - * Convert an address to a hostname. + * Convert an ipv4 address to a hostname. * * Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV * It will never resolv a hostname. @@ -217,11 +219,9 @@ gai_strerror(int errcode) */ int getnameinfo(const struct sockaddr *sa, int salen, - char *node, int nodelen, - char *service, int servicelen, int flags) + char *node, int nodelen, + char *service, int servicelen, int flags) { - int ret = -1; - /* Invalid arguments. */ if (sa == NULL || (node == NULL && service == NULL)) { @@ -242,41 +242,32 @@ getnameinfo(const struct sockaddr *sa, int salen, } #endif - if (service) + if (node) { + int ret = -1; + if (sa->sa_family == AF_INET) { - ret = snprintf(service, servicelen, "%d", - ntohs(((struct sockaddr_in *)sa)->sin_port)); - } -#ifdef HAVE_UNIX_SOCKETS - else if (sa->sa_family == AF_UNIX) - { - ret = snprintf(service, servicelen, "%s", - ((struct sockaddr_un *)sa)->sun_path); + char *p; + p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr); + ret = snprintf(node, nodelen, "%s", p); } -#endif - if (ret == -1 || ret > servicelen) + if (ret == -1 || ret > nodelen) { return EAI_MEMORY; } } - if (node) + if (service) { + 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); - } -#ifdef HAVE_UNIX_SOCKETS - else if (sa->sa_family == AF_UNIX) - { - ret = snprintf(node, nodelen, "%s", "localhost"); + ret = snprintf(service, servicelen, "%d", + ntohs(((struct sockaddr_in *)sa)->sin_port)); } -#endif - if (ret == -1 || ret > nodelen) + if (ret == -1 || ret > servicelen) { return EAI_MEMORY; } -- 2.40.0