Commit df63503d authored by Tom Lane's avatar Tom Lane

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 ...
parent 93395de0
# 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 <sys/types.h>
......@@ -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 <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
])])# PGAC_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
])])# PGAC_STRUCT_SOCKADDR_STORAGE_MEMBERS
# PGAC_STRUCT_ADDRINFO
......
......@@ -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 <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#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 <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#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 <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#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
......
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], [], [],
......
......@@ -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,8 +434,7 @@ ClientAuthentication(Port *port)
{
char hostinfo[NI_MAXHOST];
getnameinfo((struct sockaddr *) &port->raddr.addr,
port->raddr.salen,
getnameinfo_all(&port->raddr.addr, port->raddr.salen,
hostinfo, sizeof(hostinfo),
NULL, 0,
NI_NUMERICHOST);
......
......@@ -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,29 +648,31 @@ 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)
goto hba_syntax;
......@@ -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,11 +1212,11 @@ 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,
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((struct sockaddr *)&local_addr.addr, local_addr.salen,
getnameinfo_all(&local_addr.addr, local_addr.salen,
local_addr_s, sizeof(local_addr_s),
local_port, sizeof(local_port),
NI_NUMERICHOST | NI_NUMERICSERV);
......@@ -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;
}
......
......@@ -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 <nkukard@lbsd.net>, Linux Based Systems Design
......@@ -53,14 +53,19 @@ 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,
getaddrinfo_all(const char *hostname, const char *servname,
const struct addrinfo *hintp, struct addrinfo **result)
{
#ifdef HAVE_UNIX_SOCKETS
......@@ -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 */
......
......@@ -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)
{
if (hostName)
ereport(LOG,
(errmsg("failed to translate hostname to address: %s",
gai_strerror(ret))));
freeaddrinfo2(hint.ai_family, addrs);
(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;
}
......
......@@ -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);
......
......@@ -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,52 +727,58 @@ 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,
status = StreamServerPort(AF_UNSPEC, curhost,
(unsigned short) PostPortNumber,
UnixSocketDir, ListenSocket, MAXLISTEN);
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);
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)
{
......@@ -790,10 +796,11 @@ PostmasterMain(int argc, char *argv[])
#ifdef HAVE_UNIX_SOCKETS
status = StreamServerPort(AF_UNIX, NULL,
(unsigned short) PostPortNumber,
UnixSocketDir, ListenSocket, MAXLISTEN);
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,29 +1134,28 @@ 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)
{
if (fd == -1)
break;
FD_SET(fd, rmask);
if (fd > nsocks)
nsocks = fd;
}
}
return nsocks + 1;
}
......@@ -2352,16 +2359,14 @@ BackendFork(Port *port)
*/
remote_host[0] = '\0';
remote_port[0] = '\0';
if (!getnameinfo((struct sockaddr *)&port->raddr.addr,
port->raddr.salen,
if (getnameinfo_all(&port->raddr.addr, port->raddr.salen,
remote_host, sizeof(remote_host),
remote_port, sizeof(remote_host),
remote_port, sizeof(remote_port),
(log_hostname ? 0 : NI_NUMERICHOST) | NI_NUMERICSERV))
{
getnameinfo((struct sockaddr *)&port->raddr.addr,
port->raddr.salen,
getnameinfo_all(&port->raddr.addr, port->raddr.salen,
remote_host, sizeof(remote_host),
remote_port, sizeof(remote_host),
remote_port, sizeof(remote_port),
NI_NUMERICHOST | NI_NUMERICSERV);
}
......@@ -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));
......
......@@ -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 $
*
*-------------------------------------------------------------------------
*/
......
......@@ -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,
extern int getaddrinfo_all(const char *hostname, const char *servname,
const struct addrinfo *hintp,
struct addrinfo **result);
extern void freeaddrinfo2(int hint_ai_family, struct addrinfo *ai);
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
......
......@@ -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 <netinet/in.h>
#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) \
......
......@@ -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. */
......
......@@ -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)
{
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("getaddrinfo() failed: %s\n"),
libpq_gettext("could not translate local service to address: %s\n"),
gai_strerror(ret));
freeaddrinfo2(hint.ai_family, addrs);
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)
......
......@@ -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 <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef HAVE_UNIX_SOCKETS
#include <sys/un.h>
#endif
#endif
#include "getaddrinfo.h"
......@@ -124,7 +125,8 @@ getaddrinfo(const char *node, const char *service,
if (service)
sin.sin_port = htons((unsigned short) atoi(service));
#if SALEN
#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
sin.sin_len = sizeof(sin);
#endif
......@@ -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.
......@@ -220,8 +222,6 @@ getnameinfo(const struct sockaddr *sa, int salen,
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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment