aboutsummaryrefslogtreecommitdiff
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, 148 insertions, 193 deletions
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 757a8a72ce6..c3a95562b13 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.142 2002/12/06 03:46:28 momjian Exp $
+ * $Id: pqcomm.c,v 1.143 2002/12/06 04:37:02 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -85,11 +85,6 @@ 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 */
/*
@@ -187,198 +182,170 @@ int
StreamServerPort(int family, char *hostName, unsigned short portNumber,
char *unixSocketName, int *fdP)
{
- int fd,
- err;
- int maxconn;
- int one = 1;
+ SockAddr saddr;
+ int fd,
+ err;
+ int maxconn;
+ size_t len = 0;
+ int one = 1;
- int ret;
- struct addrinfo* addrs = NULL;
- struct addrinfo hint;
- char portNumberStr[64];
- char* service = portNumberStr;
- char* hostn = (hostName[0] == '\0')? NULL : hostName;
+ Assert(family == AF_INET || family == AF_UNIX);
- Assert(family == AF_INET6 || family == AF_INET || family == AF_UNIX);
+ if ((fd = socket(family, SOCK_STREAM, 0)) < 0)
+ {
+ elog(LOG, "StreamServerPort: socket() failed: %m");
+ return STATUS_ERROR;
+ }
- memset(&hint, 0, sizeof(hint));
- hint.ai_family = family;
- hint.ai_flags = AI_PASSIVE;
- hint.ai_socktype = SOCK_STREAM;
+ 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;
+ }
+ }
- snprintf(portNumberStr, sizeof(portNumberStr)/sizeof(char),
- "%d", portNumber);
+ MemSet((char *) &saddr, 0, sizeof(saddr));
+ saddr.sa.sa_family = family;
#ifdef HAVE_UNIX_SOCKETS
- if (family == AF_UNIX) {
- if(StreamServerPortSubAFUNIX1(portNumber, unixSocketName) != STATUS_OK){
- return STATUS_ERROR;
- }
- service = sock_path;
- }
+ 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);
+ }
#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);
+ }
- 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;
- }
+ saddr.in.sin_port = htons(portNumber);
+ len = sizeof(struct sockaddr_in);
+ }
-#ifdef HAVE_UNIX_SOCKETS
- if (family == AF_UNIX){
- if(StreamServerPortSubAFUNIX2() != STATUS_OK){
- freeaddrinfo2(hint.ai_family, addrs);
- return STATUS_ERROR;
- }
- }
-#endif
+ 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;
+ }
- /*
- * 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;
+#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;
+ }
+ }
-#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;
-}
+ 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;
-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;
-}
+ err = listen(fd, maxconn);
+ if (err < 0)
+ {
+ elog(LOG, "StreamServerPort: listen() failed: %m");
+ return STATUS_ERROR;
+ }
-#endif /* HAVE_UNIX_SOCKETS */
+ *fdP = fd;
+ return STATUS_OK;
+}
/*
* StreamConnection -- create a new connection with client using
@@ -424,20 +391,8 @@ 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 ( isAF_INETx(&port->laddr) )
+ if (port->laddr.sa.sa_family == AF_INET)
{
int on = 1;