summaryrefslogtreecommitdiff
path: root/src/backend/libpq/pqcomm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/libpq/pqcomm.c')
-rw-r--r--src/backend/libpq/pqcomm.c341
1 files changed, 193 insertions, 148 deletions
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 62e8bd44cd5..757a8a72ce6 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -29,7 +29,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pqcomm.c,v 1.141 2002/09/04 23:31:34 tgl Exp $
+ * $Id: pqcomm.c,v 1.142 2002/12/06 03:46:28 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -85,6 +85,11 @@ extern ssize_t secure_read(Port *, void *, size_t);
extern ssize_t secure_write(Port *, const void *, size_t);
static void pq_close(void);
+#ifdef HAVE_UNIX_SOCKETS
+int StreamServerPortSubAFUNIX1(unsigned short portNumber,
+ char *unixSocketName );
+int StreamServerPortSubAFUNIX2(void);
+#endif /* HAVE_UNIX_SOCKETS */
/*
@@ -182,171 +187,199 @@ int
StreamServerPort(int family, char *hostName, unsigned short portNumber,
char *unixSocketName, int *fdP)
{
- SockAddr saddr;
- int fd,
- err;
- int maxconn;
- size_t len = 0;
- int one = 1;
+ int fd,
+ err;
+ int maxconn;
+ int one = 1;
- Assert(family == AF_INET || family == AF_UNIX);
+ int ret;
+ struct addrinfo* addrs = NULL;
+ struct addrinfo hint;
+ char portNumberStr[64];
+ char* service = portNumberStr;
+ char* hostn = (hostName[0] == '\0')? NULL : hostName;
- if ((fd = socket(family, SOCK_STREAM, 0)) < 0)
- {
- elog(LOG, "StreamServerPort: socket() failed: %m");
- return STATUS_ERROR;
- }
+ Assert(family == AF_INET6 || family == AF_INET || family == AF_UNIX);
- if (family == AF_INET)
- {
- if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
- sizeof(one))) == -1)
- {
- elog(LOG, "StreamServerPort: setsockopt(SO_REUSEADDR) failed: %m");
- return STATUS_ERROR;
- }
- }
+ memset(&hint, 0, sizeof(hint));
+ hint.ai_family = family;
+ hint.ai_flags = AI_PASSIVE;
+ hint.ai_socktype = SOCK_STREAM;
- MemSet((char *) &saddr, 0, sizeof(saddr));
- saddr.sa.sa_family = family;
+ snprintf(portNumberStr, sizeof(portNumberStr)/sizeof(char),
+ "%d", portNumber);
#ifdef HAVE_UNIX_SOCKETS
- if (family == AF_UNIX)
- {
- UNIXSOCK_PATH(saddr.un, portNumber, unixSocketName);
- len = UNIXSOCK_LEN(saddr.un);
- strcpy(sock_path, saddr.un.sun_path);
-
- /*
- * Grab an interlock file associated with the socket file.
- */
- if (!CreateSocketLockFile(sock_path, true))
- return STATUS_ERROR;
-
- /*
- * Once we have the interlock, we can safely delete any
- * pre-existing socket file to avoid failure at bind() time.
- */
- unlink(sock_path);
- }
+ if (family == AF_UNIX) {
+ if(StreamServerPortSubAFUNIX1(portNumber, unixSocketName) != STATUS_OK){
+ return STATUS_ERROR;
+ }
+ service = sock_path;
+ }
#endif /* HAVE_UNIX_SOCKETS */
- if (family == AF_INET)
- {
- /* TCP/IP socket */
- if (hostName[0] == '\0')
- saddr.in.sin_addr.s_addr = htonl(INADDR_ANY);
- else
- {
- struct hostent *hp;
- hp = gethostbyname(hostName);
- if ((hp == NULL) || (hp->h_addrtype != AF_INET))
- {
- elog(LOG, "StreamServerPort: gethostbyname(%s) failed",
- hostName);
- return STATUS_ERROR;
- }
- memmove((char *) &(saddr.in.sin_addr), (char *) hp->h_addr,
- hp->h_length);
- }
- saddr.in.sin_port = htons(portNumber);
- len = sizeof(struct sockaddr_in);
- }
-
- err = bind(fd, (struct sockaddr *) & saddr.sa, len);
- if (err < 0)
- {
- if (family == AF_UNIX)
- elog(LOG, "StreamServerPort: bind() failed: %m\n"
- "\tIs another postmaster already running on port %d?\n"
- "\tIf not, remove socket node (%s) and retry.",
- (int) portNumber, sock_path);
- else
- elog(LOG, "StreamServerPort: bind() failed: %m\n"
- "\tIs another postmaster already running on port %d?\n"
- "\tIf not, wait a few seconds and retry.",
- (int) portNumber);
- return STATUS_ERROR;
- }
+ ret = getaddrinfo2(hostn, service, &hint, &addrs);
+ if(ret || addrs == NULL){
+ elog(LOG, "FATAL: StreamServerPort: getaddrinfo2() failed: %s\n",
+ gai_strerror(ret));
+ freeaddrinfo2(hint.ai_family, addrs);
+ return STATUS_ERROR;
+ }
+
+
+ /** YY DEBUG
+ if(addrs->ai_family == AF_UNIX){
+ printf("%s-%s-%s \n", "debug: AF_UNIX!", unixSocketName, hostName);
+ }
+ else {
+ printf("%s", "debug: NOT AF_UNIX!\n");
+ }
+ fflush(stdout);
+ **/
+
+ if( (fd = socket(addrs->ai_family, SOCK_STREAM, 0)) < 0){
+ elog(LOG, "FATAL: StreamServerPort: socket() failed: %s\n",
+ strerror(errno));
+ freeaddrinfo2(hint.ai_family, addrs);
+ return STATUS_ERROR;
+ }
+
+ if( isAF_INETx2(family) ){
+ if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one,
+ sizeof(one) )) == -1 ){
+ elog(LOG, "FATAL: StreamServerPort: setsockopt(SO_REUSEADDR) failed: %s\n",
+ strerror(errno));
+ freeaddrinfo2(hint.ai_family, addrs);
+ return STATUS_ERROR;
+ }
+ }
+
+
+ err = bind(fd, addrs->ai_addr, addrs->ai_addrlen);
+ if(err < 0){
+ elog(LOG, "FATAL: StreamServerPort: bind() failed: %s\n"
+ "\tIs another postmaster already running on port %d?\n",
+ strerror(errno), (int) portNumber);
+ if (family == AF_UNIX)
+ elog(LOG, "\tIf not, remove socket node (%s) and retry.\n",
+ sock_path);
+ else
+ elog(LOG, "\tIf not, wait a few seconds and retry.\n");
+ freeaddrinfo2(hint.ai_family, addrs);
+ return STATUS_ERROR;
+ }
#ifdef HAVE_UNIX_SOCKETS
- if (family == AF_UNIX)
- {
- /* Arrange to unlink the socket file at exit */
- on_proc_exit(StreamDoUnlink, 0);
-
- /*
- * Fix socket ownership/permission if requested. Note we must do
- * this before we listen() to avoid a window where unwanted
- * connections could get accepted.
- */
- Assert(Unix_socket_group);
- if (Unix_socket_group[0] != '\0')
- {
- char *endptr;
- unsigned long int val;
- gid_t gid;
-
- val = strtoul(Unix_socket_group, &endptr, 10);
- if (*endptr == '\0')
- {
- /* numeric group id */
- gid = val;
- }
- else
- {
- /* convert group name to id */
- struct group *gr;
-
- gr = getgrnam(Unix_socket_group);
- if (!gr)
- {
- elog(LOG, "No such group as '%s'",
- Unix_socket_group);
- return STATUS_ERROR;
- }
- gid = gr->gr_gid;
- }
- if (chown(sock_path, -1, gid) == -1)
- {
- elog(LOG, "Could not set group of %s: %m",
- sock_path);
- return STATUS_ERROR;
- }
- }
+ if (family == AF_UNIX){
+ if(StreamServerPortSubAFUNIX2() != STATUS_OK){
+ freeaddrinfo2(hint.ai_family, addrs);
+ return STATUS_ERROR;
+ }
+ }
+#endif
- if (chmod(sock_path, Unix_socket_permissions) == -1)
- {
- elog(LOG, "Could not set permissions on %s: %m",
- sock_path);
- return STATUS_ERROR;
- }
- }
-#endif /* HAVE_UNIX_SOCKETS */
+ /*
+ * Select appropriate accept-queue length limit. PG_SOMAXCONN is only
+ * intended to provide a clamp on the request on platforms where an
+ * overly large request provokes a kernel error (are there any?).
+ */
+ maxconn = MaxBackends * 2;
+ if (maxconn > PG_SOMAXCONN)
+ maxconn = PG_SOMAXCONN;
+
+ err = listen(fd, maxconn);
+ if (err < 0) {
+ elog(LOG, "FATAL: StreamServerPort: listen() failed: %s\n",
+ strerror(errno));
+ freeaddrinfo2(hint.ai_family, addrs);
+ return STATUS_ERROR;
+ }
+
+ *fdP = fd;
+ freeaddrinfo2(hint.ai_family, addrs);
+ return STATUS_OK;
- /*
- * Select appropriate accept-queue length limit. PG_SOMAXCONN is only
- * intended to provide a clamp on the request on platforms where an
- * overly large request provokes a kernel error (are there any?).
- */
- maxconn = MaxBackends * 2;
- if (maxconn > PG_SOMAXCONN)
- maxconn = PG_SOMAXCONN;
+}
- err = listen(fd, maxconn);
- if (err < 0)
- {
- elog(LOG, "StreamServerPort: listen() failed: %m");
- return STATUS_ERROR;
- }
+#ifdef HAVE_UNIX_SOCKETS
+int StreamServerPortSubAFUNIX1(unsigned short portNumber,
+ char *unixSocketName )
+{
+ SockAddr saddr;
+ int len;
+
+ MemSet((char *) &saddr, 0, sizeof(saddr));
+
+ UNIXSOCK_PATH(saddr.un, portNumber, unixSocketName);
+ len = UNIXSOCK_LEN(saddr.un);
+ strcpy(sock_path, saddr.un.sun_path);
+
+ /*
+ * Grab an interlock file associated with the socket file.
+ */
+ if (!CreateSocketLockFile(sock_path, true))
+ return STATUS_ERROR;
+
+ /*
+ * Once we have the interlock, we can safely delete any
+ * pre-existing socket file to avoid failure at bind() time.
+ */
+ unlink(sock_path);
+
+ return STATUS_OK;
+}
- *fdP = fd;
- return STATUS_OK;
+int StreamServerPortSubAFUNIX2(void)
+{
+ /* Arrange to unlink the socket file at exit */
+ on_proc_exit(StreamDoUnlink, 0);
+
+ /*
+ * Fix socket ownership/permission if requested. Note we must do
+ * this before we listen() to avoid a window where unwanted
+ * connections could get accepted.
+ */
+ Assert(Unix_socket_group);
+ if (Unix_socket_group[0] != '\0') {
+ char *endptr;
+ unsigned long int val;
+ gid_t gid;
+
+ val = strtoul(Unix_socket_group, &endptr, 10);
+ if (*endptr == '\0'){ /* numeric group id */
+ gid = val;
+ }
+ else { /* convert group name to id */
+ struct group *gr;
+ gr = getgrnam(Unix_socket_group);
+ if (!gr) {
+ elog(LOG, "FATAL: no such group '%s'\n",
+ Unix_socket_group);
+ return STATUS_ERROR;
+ }
+ gid = gr->gr_gid;
+ }
+ if (chown(sock_path, -1, gid) == -1){
+ elog(LOG, "FATAL: could not set group of %s: %s\n",
+ sock_path, strerror(errno));
+ return STATUS_ERROR;
+ }
+ }
+
+ if (chmod(sock_path, Unix_socket_permissions) == -1){
+ elog(LOG, "FATAL: could not set permissions on %s: %s\n",
+ sock_path, strerror(errno));
+ return STATUS_ERROR;
+ }
+ return STATUS_OK;
}
+#endif /* HAVE_UNIX_SOCKETS */
+
+
/*
* StreamConnection -- create a new connection with client using
* server port.
@@ -391,8 +424,20 @@ StreamConnection(int server_fd, Port *port)
return STATUS_ERROR;
}
+ /* DEBUG YY
+ {
+ char l_hostinfo[INET6_ADDRSTRLEN];
+ char r_hostinfo[INET6_ADDRSTRLEN];
+ SockAddr_ntop(&port->laddr, l_hostinfo, INET6_ADDRSTRLEN, 1);
+ SockAddr_ntop(&port->raddr, r_hostinfo, INET6_ADDRSTRLEN, 1);
+ printf("StreamConnect() l: %s r: %s\n", l_hostinfo, r_hostinfo);
+ printf("StreamConnect() l: %d r: %d\n", port->laddr.sa.sa_family,
+ port->raddr.sa.sa_family);
+ }
+ */
+
/* select NODELAY and KEEPALIVE options if it's a TCP connection */
- if (port->laddr.sa.sa_family == AF_INET)
+ if ( isAF_INETx(&port->laddr) )
{
int on = 1;