diff options
author | Bruce Momjian <bruce@momjian.us> | 2002-12-06 03:46:37 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2002-12-06 03:46:37 +0000 |
commit | 8fc86dd593b9e9a2b24779e263ad33c37e15c9f9 (patch) | |
tree | 39402a6de176f209744c1fdedbcc18c28352f34e /src/interfaces/libpq/fe-connect.c | |
parent | 87cba401a48feff7e547f59fb7ead1a1ab99042a (diff) | |
download | postgresql-8fc86dd593b9e9a2b24779e263ad33c37e15c9f9.tar.gz postgresql-8fc86dd593b9e9a2b24779e263ad33c37e15c9f9.zip |
We have just finished porting the old KAME IPv6 patch over to
postgresql version 7.3, but yea... this patch adds full IPv6
support to postgres. I've tested it out on 7.2.3 and has
been running perfectly stable.
CREDITS:
The KAME Project (Initial patch)
Nigel Kukard <nkukard@lbsd.net>
Johan Jordaan <johanj@lando.co.za>
Diffstat (limited to 'src/interfaces/libpq/fe-connect.c')
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 193 |
1 files changed, 92 insertions, 101 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 7cdd2466624..36782ecf70f 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.213 2002/10/24 23:35:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.214 2002/12/06 03:46:37 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -39,6 +39,9 @@ #include <arpa/inet.h> #endif +#include "libpq/v6util.h" + + #ifndef HAVE_STRDUP #include "strdup.h" #endif @@ -786,6 +789,15 @@ 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 */ @@ -815,101 +827,67 @@ connectDBStart(PGconn *conn) MemSet((char *) &conn->raddr, 0, sizeof(conn->raddr)); - 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)); + 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; } - 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); + else if (conn->pghost != NULL && conn->pghost[0] != '\0'){ + node = conn->pghost; + hint.ai_family = AF_UNSPEC; } - else - { - /* pghostaddr and pghost are NULL, so use Unix domain socket */ - family = AF_UNIX; +#ifdef HAVE_UNIX_SOCKETS + else { + node = unix_node; + hint.ai_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 (family == AF_INET) - { - conn->raddr.in.sin_port = htons((unsigned short) (portno)); - conn->raddr_len = sizeof(struct sockaddr_in); + portno = DEF_PGPORT; + + if(hint.ai_family == AF_UNSPEC){ + snprintf(portNoStr, sizeof(portNoStr)/sizeof(char), + "%d", portno); } #ifdef HAVE_UNIX_SOCKETS - else - { - UNIXSOCK_PATH(conn->raddr.un, portno, conn->pgunixsocket); - conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un); + else { + UNIXSOCK_PATH(conn->raddr.un, portno, conn->pgunixsocket); + conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un); + strcpy(portNoStr, conn->raddr.un.sun_path); #ifdef USE_SSL /* Don't bother requesting SSL over a Unix socket */ conn->allow_ssl_try = false; conn->require_ssl = false; #endif } -#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; +#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; } - + 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 /* ---------- @@ -922,31 +900,42 @@ connectDBStart(PGconn *conn) * ---------- */ retry1: - if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0) - { + if(connect(sockfd, addr_cur->ai_addr, addr_cur->ai_addrlen) == 0){ + /* We're connected already */ + conn->status = CONNECTION_MADE; + break; + } + else { 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; - } - else - { - /* Something's gone wrong */ - connectFailureMessage(conn, 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; + 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; } - else - { - /* We're connected already */ - conn->status = CONNECTION_MADE; + 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; } #ifdef USE_SSL @@ -1038,7 +1027,9 @@ connect_errReturn: conn->sock = -1; } conn->status = CONNECTION_BAD; - + if(addrs != NULL){ + freeaddrinfo2(hint.ai_family, addrs); + } return 0; } |