mirror of
https://github.com/postgres/postgres.git
synced 2025-06-26 12:21:12 +03:00
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 ...
This commit is contained in:
@ -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),
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,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 */
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,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))
|
||||
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((struct sockaddr *)&port->raddr.addr,
|
||||
port->raddr.salen,
|
||||
remote_host, sizeof(remote_host),
|
||||
remote_port, sizeof(remote_host),
|
||||
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));
|
||||
|
Reference in New Issue
Block a user