Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)