Skip to content

Commit e8a10dc

Browse files
committed
Fix some of the breakage from the IPV6 patch.
1 parent 874e8ce commit e8a10dc

File tree

1 file changed

+87
-51
lines changed

1 file changed

+87
-51
lines changed

src/interfaces/libpq/fe-connect.c

Lines changed: 87 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.222 2003/01/30 19:49:54 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.223 2003/02/14 01:24:26 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -800,7 +800,6 @@ static int
800800
connectDBStart(PGconn *conn)
801801
{
802802
int portnum;
803-
int sockfd;
804803
char portstr[64];
805804
#ifdef USE_SSL
806805
StartupPacket np; /* Used to negotiate SSL connection */
@@ -837,19 +836,17 @@ connectDBStart(PGconn *conn)
837836
conn->outCount = 0;
838837

839838
/*
840-
* Set up the connection to postmaster/backend. Note that this
841-
* supports IPv4 and UDP only.
842-
*/
843-
844-
MemSet((char *) &conn->raddr, 0, sizeof(conn->raddr));
845-
846-
/*
839+
* Set up the connection to postmaster/backend.
840+
*
847841
* This code is confusing because IPv6 creates a hint structure
848842
* that is passed to getaddrinfo2(), which returns a list of address
849843
* structures that are looped through, while IPv4 creates an address
850844
* structure directly.
851845
*/
852846

847+
MemSet((char *) &conn->raddr, 0, sizeof(conn->raddr));
848+
849+
/* Set port number */
853850
if (conn->pgport != NULL && conn->pgport[0] != '\0')
854851
portnum = atoi(conn->pgport);
855852
else
@@ -875,8 +872,8 @@ connectDBStart(PGconn *conn)
875872

876873
family = AF_INET;
877874

878-
memmove((char *) &(conn->raddr.in.sin_addr),
879-
(char *) &addr, sizeof(addr));
875+
memcpy((char *) &(conn->raddr.in.sin_addr),
876+
(char *) &addr, sizeof(addr));
880877
#endif
881878
}
882879
else if (conn->pghost != NULL && conn->pghost[0] != '\0')
@@ -892,36 +889,39 @@ connectDBStart(PGconn *conn)
892889
family = AF_INET;
893890
#endif
894891
}
895-
#ifdef HAVE_UNIX_SOCKETS
896892
else
897893
{
894+
#ifdef HAVE_UNIX_SOCKETS
898895
#ifdef HAVE_IPV6
899896
node = unix_node;
900897
hint.ai_family = AF_UNIX;
901898
#else
902899
/* pghostaddr and pghost are NULL, so use Unix domain socket */
903900
family = AF_UNIX;
904901
#endif
905-
}
906902
#endif /* HAVE_UNIX_SOCKETS */
903+
}
907904

908905
#ifndef HAVE_IPV6
906+
/* Set family */
909907
conn->raddr.sa.sa_family = family;
910908
#endif
911909

912910
#ifdef HAVE_IPV6
913911
if (hint.ai_family == AF_UNSPEC)
914-
{/* do nothing*/}
912+
{
913+
/* do nothing */
914+
}
915915
#else
916916
if (family == AF_INET)
917917
{
918918
conn->raddr.in.sin_port = htons((unsigned short) (portnum));
919919
conn->raddr_len = sizeof(struct sockaddr_in);
920920
}
921921
#endif
922-
#ifdef HAVE_UNIX_SOCKETS
923922
else
924923
{
924+
#ifdef HAVE_UNIX_SOCKETS
925925
UNIXSOCK_PATH(conn->raddr.un, portnum, conn->pgunixsocket);
926926
conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un);
927927
StrNCpy(portstr, conn->raddr.un.sun_path, sizeof(portstr));
@@ -930,10 +930,11 @@ connectDBStart(PGconn *conn)
930930
conn->allow_ssl_try = false;
931931
conn->require_ssl = false;
932932
#endif
933-
}
934933
#endif /* HAVE_UNIX_SOCKETS */
934+
}
935935

936-
#if HAVE_IPV6
936+
#ifdef HAVE_IPV6
937+
/* Use getaddrinfo2() to resolve the address */
937938
ret = getaddrinfo2(node, portstr, &hint, &addrs);
938939
if (ret || addrs == NULL)
939940
{
@@ -942,21 +943,52 @@ connectDBStart(PGconn *conn)
942943
gai_strerror(ret));
943944
goto connect_errReturn;
944945
}
945-
addr_cur = addrs;
946946
#endif
947947

948-
do
948+
/*
949+
* For IPV6 we loop over the possible addresses returned by
950+
* getaddrinfo2(), and fail only when they all fail (reporting the
951+
* error returned for the *last* alternative, which may not be what
952+
* users expect :-(). Otherwise, there is no true loop here.
953+
*
954+
* In either case, we never actually fall out of the loop; the
955+
* only exits are via "break" or "goto connect_errReturn". Thus,
956+
* there is no exit test in the for().
957+
*/
958+
for (
959+
#ifdef HAVE_IPV6
960+
addr_cur = addrs; ; addr_cur = addr_cur->ai_next
961+
#else
962+
;;
963+
#endif
964+
)
949965
{
966+
/* Open a socket */
950967
#ifdef HAVE_IPV6
951-
sockfd = socket(addr_cur->ai_family, SOCK_STREAM,
952-
addr_cur->ai_protocol);
968+
conn->sock = socket(addr_cur->ai_family, SOCK_STREAM,
969+
addr_cur->ai_protocol);
953970
#else
954-
sockfd = socket(family, SOCK_STREAM, 0);
971+
conn->sock = socket(family, SOCK_STREAM, 0);
955972
#endif
956-
if (sockfd < 0)
957-
continue;
973+
if (conn->sock < 0)
974+
{
975+
#ifdef HAVE_IPV6
976+
/* ignore socket() failure if we have more addrs to try */
977+
if (addr_cur->ai_next != NULL)
978+
continue;
979+
#endif
980+
printfPQExpBuffer(&conn->errorMessage,
981+
libpq_gettext("could not create socket: %s\n"),
982+
SOCK_STRERROR(SOCK_ERRNO));
983+
goto connect_errReturn;
984+
}
985+
986+
/*
987+
* Set the right options. Normally, we need nonblocking I/O, and we
988+
* don't want delay of outgoing data for AF_INET sockets. If we are
989+
* using SSL, then we need the blocking I/O (XXX Can this be fixed?).
990+
*/
958991

959-
conn->sock = sockfd;
960992
#ifdef HAVE_IPV6
961993
if (isAF_INETx(addr_cur->ai_family))
962994
#else
@@ -966,6 +998,7 @@ connectDBStart(PGconn *conn)
966998
if (!connectNoDelay(conn))
967999
goto connect_errReturn;
9681000
}
1001+
9691002
#if !defined(USE_SSL)
9701003
if (connectMakeNonblocking(conn) == 0)
9711004
goto connect_errReturn;
@@ -982,16 +1015,10 @@ connectDBStart(PGconn *conn)
9821015
*/
9831016
retry1:
9841017
#ifdef HAVE_IPV6
985-
if (connect(sockfd, addr_cur->ai_addr, addr_cur->ai_addrlen) == 0)
1018+
if (connect(conn->sock, addr_cur->ai_addr, addr_cur->ai_addrlen) < 0)
9861019
#else
987-
if (connect(sockfd, &conn->raddr.sa, conn->raddr_len) == 0)
1020+
if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0)
9881021
#endif
989-
{
990-
/* We're connected already */
991-
conn->status = CONNECTION_MADE;
992-
break;
993-
}
994-
else
9951022
{
9961023
if (SOCK_ERRNO == EINTR)
9971024
/* Interrupted system call - we'll just try again */
@@ -1006,30 +1033,39 @@ connectDBStart(PGconn *conn)
10061033
conn->status = CONNECTION_STARTED;
10071034
break;
10081035
}
1036+
/* otherwise, trouble */
1037+
}
1038+
else
1039+
{
1040+
/* We're connected already */
1041+
conn->status = CONNECTION_MADE;
1042+
break;
10091043
}
1010-
close(sockfd);
1044+
/*
1045+
* This connection failed. We need to close the socket,
1046+
* and either loop to try the next address or report an error.
1047+
*/
10111048
#ifdef HAVE_IPV6
1012-
} while ((addr_cur = addr_cur->ai_next) != NULL);
1013-
if (addr_cur == NULL)
1014-
#else
1015-
} while (0);
1016-
if (sockfd < 0)
1049+
/* ignore connect() failure if we have more addrs to try */
1050+
if (addr_cur->ai_next != NULL)
1051+
{
1052+
close(conn->sock);
1053+
conn->sock = -1;
1054+
continue;
1055+
}
10171056
#endif
1018-
{
1019-
printfPQExpBuffer(&conn->errorMessage,
1020-
libpq_gettext("could not create socket: %s\n"),
1021-
SOCK_STRERROR(SOCK_ERRNO));
1057+
connectFailureMessage(conn, SOCK_ERRNO);
10221058
goto connect_errReturn;
1023-
}
1024-
else
1025-
{
1059+
} /* loop over addrs */
1060+
10261061
#ifdef HAVE_IPV6
1027-
memmove(&conn->raddr, addr_cur->ai_addr, addr_cur->ai_addrlen);
1028-
conn->raddr_len = addr_cur->ai_addrlen;
1029-
FREEADDRINFO2(hint.ai_family, addrs);
1030-
addrs = NULL;
1062+
/* Remember the successfully opened address alternative */
1063+
memcpy(&conn->raddr, addr_cur->ai_addr, addr_cur->ai_addrlen);
1064+
conn->raddr_len = addr_cur->ai_addrlen;
1065+
/* and release the address list */
1066+
FREEADDRINFO2(hint.ai_family, addrs);
1067+
addrs = NULL;
10311068
#endif
1032-
}
10331069

10341070
#ifdef USE_SSL
10351071
/* Attempt to negotiate SSL usage */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy