summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoff Garside <geoff@geoffgarside.co.uk>2011-06-17 01:06:19 +0100
committerantirez <antirez@gmail.com>2013-07-08 15:49:22 +0200
commit0e01ce1b13c4e0a974dc4009dc78811a234f0244 (patch)
tree46658d53d6827eea3a5358e739bc5d5381ec0a61
parent580b7dce9b1d7adac1d0bfe33e5023f8fbf91158 (diff)
downloadredis-0e01ce1b13c4e0a974dc4009dc78811a234f0244.tar.gz
Use getaddrinfo(3) in anetTcpGenericConnect.
Change anetTcpGenericConnect() function to use getaddrinfo(3) to perform address resolution, socket creation and connection. Resolved addresses are limited to those reachable by the AF_INET family.
-rw-r--r--src/anet.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/src/anet.c b/src/anet.c
index 78c24bf25..bbff3e3e9 100644
--- a/src/anet.c
+++ b/src/anet.c
@@ -217,38 +217,52 @@ static int anetCreateSocket(char *err, int domain) {
#define ANET_CONNECT_NONBLOCK 1
static int anetTcpGenericConnect(char *err, char *addr, int port, int flags)
{
- int s;
- struct sockaddr_in sa;
+ int s, rv;
+ char _port[6]; /* strlen("65535"); */
+ struct addrinfo hints, *servinfo, *p;
- if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR)
+ snprintf(_port,6,"%d",port);
+ memset(&hints,0,sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
+ anetSetError(err, "%s", gai_strerror(rv));
return ANET_ERR;
+ }
+ for (p = servinfo; p != NULL; p = p->ai_next) {
+ if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
+ continue;
- sa.sin_family = AF_INET;
- sa.sin_port = htons(port);
- if (inet_aton(addr, &sa.sin_addr) == 0) {
- struct hostent *he;
+ /* if we set err then goto cleanup, otherwise next */
+ if (anetSetReuseAddr(err,s) == ANET_ERR) {
+ goto error;
+ }
+ if (flags & ANET_CONNECT_NONBLOCK) {
+ if (anetNonBlock(err,s) != ANET_OK)
+ goto error;
+ }
+ if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
+ if (errno == EINPROGRESS &&
+ flags & ANET_CONNECT_NONBLOCK)
+ goto end;
- he = gethostbyname(addr);
- if (he == NULL) {
- anetSetError(err, "can't resolve: %s", addr);
close(s);
- return ANET_ERR;
+ continue;
}
- memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
+
+ /* break with the socket */
+ goto end;
}
- if (flags & ANET_CONNECT_NONBLOCK) {
- if (anetNonBlock(err,s) != ANET_OK)
- return ANET_ERR;
+ if (p == NULL) {
+ anetSetError(err, "creating socket: %s", strerror(errno));
+ goto error;
}
- if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
- if (errno == EINPROGRESS &&
- flags & ANET_CONNECT_NONBLOCK)
- return s;
- anetSetError(err, "connect: %s", strerror(errno));
- close(s);
- return ANET_ERR;
- }
+error:
+ s = ANET_ERR;
+end:
+ freeaddrinfo(servinfo);
return s;
}