/*
- * $Id$
- *
* This module handles client-side sockets opened by the Citadel server (for
* the client side of Internet protocols, etc.) It does _not_ handle client
* sockets for the Citadel client; for that you must look in ipc_c_tcp.c
int sock_connect(char *host, char *service)
{
struct in6_addr serveraddr;
- struct addrinfo hints, *res = NULL;
- int rc;
+ struct addrinfo hints;
+ struct addrinfo *res = NULL;
+ struct addrinfo *ai = NULL;
+ int rc = (-1);
int sock = (-1);
if ((host == NULL) || IsEmptyStr(host))
return(-1);
}
- sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (sock < 0) {
- CtdlLogPrintf(CTDL_ERR, "socket() failed: %s\n", strerror(errno));
- return(-1);
- }
-
- rc = connect(sock, res->ai_addr, res->ai_addrlen);
- if (rc < 0) {
- /*
- * Note: the res is a linked list of addresses found for server.
- * If the connect() fails to the first one, subsequent addresses
- * (if any) in the list could be tried if desired.
- */
- CtdlLogPrintf(CTDL_ERR, "connect() failed: %s\n", strerror(errno));
- return(-1);
+ /*
+ * Try all available addresses until we connect to one or until we run out.
+ */
+ for (ai = res; ai != NULL; ai = ai->ai_next) {
+ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (sock < 0) {
+ CtdlLogPrintf(CTDL_ERR, "socket() failed: %s\n", strerror(errno));
+ return(-1);
+ }
+ rc = connect(sock, ai->ai_addr, ai->ai_addrlen);
+ if (rc >= 0) {
+ return(sock);
+ }
+ else {
+ CtdlLogPrintf(CTDL_ERR, "connect() failed: %s\n", strerror(errno));
+ close(sock);
+ }
}
- return (sock);
+ return(-1);
}