diff options
Diffstat (limited to 'src/interfaces/libpq/fe-connect.c')
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 193 |
1 files changed, 101 insertions, 92 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 36782ecf70f..3bf194fa7ab 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.214 2002/12/06 03:46:37 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.215 2002/12/06 04:37:05 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -39,9 +39,6 @@ #include <arpa/inet.h> #endif -#include "libpq/v6util.h" - - #ifndef HAVE_STRDUP #include "strdup.h" #endif @@ -789,15 +786,6 @@ connectDBStart(PGconn *conn) { int portno, family; - struct addrinfo* addrs = NULL; - struct addrinfo* addr_cur = NULL; - struct addrinfo hint; - const char* node = NULL; - const char* unix_node = "unix"; - char portNoStr[64]; - int ret; - int sockfd; - #ifdef USE_SSL StartupPacket np; /* Used to negotiate SSL connection */ @@ -827,67 +815,101 @@ connectDBStart(PGconn *conn) MemSet((char *) &conn->raddr, 0, sizeof(conn->raddr)); - MemSet(&hint, 0, sizeof(hint)); - hint.ai_socktype = SOCK_STREAM; - if(conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0'){ - node = conn->pghostaddr; - hint.ai_family = AF_UNSPEC; + if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0') + { + /* Using pghostaddr avoids a hostname lookup */ + /* Note that this supports IPv4 only */ + struct in_addr addr; + + if (!inet_aton(conn->pghostaddr, &addr)) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("invalid host address: %s\n"), + conn->pghostaddr); + goto connect_errReturn; + } + + family = AF_INET; + + memmove((char *) &(conn->raddr.in.sin_addr), + (char *) &addr, sizeof(addr)); } - else if (conn->pghost != NULL && conn->pghost[0] != '\0'){ - node = conn->pghost; - hint.ai_family = AF_UNSPEC; + else if (conn->pghost != NULL && conn->pghost[0] != '\0') + { + /* Using pghost, so we have to look-up the hostname */ + struct hostent *hp; + + hp = gethostbyname(conn->pghost); + if ((hp == NULL) || (hp->h_addrtype != AF_INET)) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("unknown host name: %s\n"), + conn->pghost); + goto connect_errReturn; + } + family = AF_INET; + + memmove((char *) &(conn->raddr.in.sin_addr), + (char *) hp->h_addr, + hp->h_length); } -#ifdef HAVE_UNIX_SOCKETS - else { - node = unix_node; - hint.ai_family = AF_UNIX; + else + { + /* pghostaddr and pghost are NULL, so use Unix domain socket */ + family = AF_UNIX; } -#endif /* HAVE_UNIX_SOCKETS */ + /* Set family */ + conn->raddr.sa.sa_family = family; + + /* Set port number */ if (conn->pgport != NULL && conn->pgport[0] != '\0') - portno = atoi(conn->pgport); + portno = atoi(conn->pgport); else - portno = DEF_PGPORT; - - if(hint.ai_family == AF_UNSPEC){ - snprintf(portNoStr, sizeof(portNoStr)/sizeof(char), - "%d", portno); + portno = DEF_PGPORT; + + if (family == AF_INET) + { + conn->raddr.in.sin_port = htons((unsigned short) (portno)); + conn->raddr_len = sizeof(struct sockaddr_in); } #ifdef HAVE_UNIX_SOCKETS - else { - UNIXSOCK_PATH(conn->raddr.un, portno, conn->pgunixsocket); - conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un); - strcpy(portNoStr, conn->raddr.un.sun_path); + else + { + UNIXSOCK_PATH(conn->raddr.un, portno, conn->pgunixsocket); + conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un); #ifdef USE_SSL /* Don't bother requesting SSL over a Unix socket */ conn->allow_ssl_try = false; conn->require_ssl = false; #endif } -#endif /* HAVE_UNIX_SOCKETS */ - - ret = getaddrinfo2(node, portNoStr, &hint, &addrs); - if(ret || addrs == NULL){ - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("failed to getaddrinfo(): %s\n"), - gai_strerror(ret) ); - goto connect_errReturn; +#endif + + /* Open a socket */ + if ((conn->sock = socket(family, SOCK_STREAM, 0)) < 0) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("could not create socket: %s\n"), + SOCK_STRERROR(SOCK_ERRNO)); + goto connect_errReturn; + } + + /* + * Set the right options. Normally, we need nonblocking I/O, and we + * don't want delay of outgoing data for AF_INET sockets. If we are + * using SSL, then we need the blocking I/O (XXX Can this be fixed?). + */ + + if (family == AF_INET) + { + if (!connectNoDelay(conn)) + goto connect_errReturn; } - addr_cur = addrs; - do { - sockfd = socket(addr_cur->ai_family, addr_cur->ai_socktype, - addr_cur->ai_protocol); - if(sockfd < 0){ - continue; - } - conn->sock = sockfd; - if (isAF_INETx2(addr_cur->ai_family) ){ - if (!connectNoDelay(conn)) - goto connect_errReturn; - } + #if !defined(USE_SSL) - if (connectMakeNonblocking(conn) == 0) - goto connect_errReturn; + if (connectMakeNonblocking(conn) == 0) + goto connect_errReturn; #endif /* ---------- @@ -900,42 +922,31 @@ connectDBStart(PGconn *conn) * ---------- */ retry1: - if(connect(sockfd, addr_cur->ai_addr, addr_cur->ai_addrlen) == 0){ - /* We're connected already */ - conn->status = CONNECTION_MADE; - break; - } - else { + if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0) + { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ goto retry1; - if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || SOCK_ERRNO == 0){ - - /* - * This is fine - we're in non-blocking mode, and the - * connection is in progress. - */ - conn->status = CONNECTION_STARTED; - break; - } - } - close(sockfd); - } while( (addr_cur = addr_cur->ai_next) != NULL); - - if(addr_cur == NULL){ - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("could not create socket: %s\n"), - SOCK_STRERROR(SOCK_ERRNO)); - - goto connect_errReturn; + if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || SOCK_ERRNO == 0) + { + /* + * This is fine - we're in non-blocking mode, and the + * connection is in progress. + */ + conn->status = CONNECTION_STARTED; + } + else + { + /* Something's gone wrong */ + connectFailureMessage(conn, SOCK_ERRNO); + goto connect_errReturn; + } } - else { - family = addr_cur->ai_family; - memmove(&conn->raddr, addr_cur->ai_addr, addr_cur->ai_addrlen); - conn->raddr_len = addr_cur->ai_addrlen; - freeaddrinfo2(hint.ai_family, addrs); - addrs = NULL; + else + { + /* We're connected already */ + conn->status = CONNECTION_MADE; } #ifdef USE_SSL @@ -1027,9 +1038,7 @@ connect_errReturn: conn->sock = -1; } conn->status = CONNECTION_BAD; - if(addrs != NULL){ - freeaddrinfo2(hint.ai_family, addrs); - } + return 0; } |