summaryrefslogtreecommitdiffstats
path: root/ares_process.c
diff options
context:
space:
mode:
Diffstat (limited to 'ares_process.c')
-rw-r--r--ares_process.c90
1 files changed, 67 insertions, 23 deletions
diff --git a/ares_process.c b/ares_process.c
index 71f9394..689d1c1 100644
--- a/ares_process.c
+++ b/ares_process.c
@@ -434,7 +434,7 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds,
ssize_t count;
unsigned char buf[PACKETSZ + 1];
#ifdef HAVE_RECVFROM
- struct sockaddr_in from;
+ struct sockaddr_storage from;
ares_socklen_t fromlen;
#endif
@@ -480,16 +480,32 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds,
if (count == -1 && try_again(SOCKERRNO))
continue;
else if (count <= 0)
- handle_error(channel, i, now);
+ {
+ handle_error(channel, i, now);
+ break;
+ }
#ifdef HAVE_RECVFROM
- else if (from.sin_addr.s_addr != server->addr.s_addr)
- /* Address response came from did not match the address
- * we sent the request to. Someone may be attempting
- * to perform a cache poisoning attack */
- break;
+ /* Check if address response came from did match the address
+ * we sent the request to. Someone may be attempting
+ * to perform a cache poisoning attack */
+ else if (from.ss_family == AF_INET)
+ {
+ struct sockaddr_in *from4 = (struct sockaddr_in *) &from;
+ struct sockaddr_in *srv4 = (struct sockaddr_in *) server->addr->ai_addr;
+ if (from4->sin_addr.s_addr != srv4->sin_addr.s_addr)
+ break;
+ }
+ else if (from.ss_family == AF_INET6)
+ {
+ struct sockaddr_in6 *from6 = (struct sockaddr_in6 *) &from;
+ struct sockaddr_in6 *srv6 = (struct sockaddr_in6 *) server->addr->ai_addr;
+ if (memcmp(from6->sin6_addr.s6_addr,
+ srv6->sin6_addr.s6_addr,
+ 16)) /* FIXME - is there any portable constant? */
+ break;
+ }
#endif
- else
- process_answer(channel, buf, (int)count, i, 0, now);
+ process_answer(channel, buf, (int)count, i, 0, now);
} while (count > 0);
}
}
@@ -889,14 +905,39 @@ static int configure_socket(ares_socket_t s, ares_channel channel)
return 0;
}
+static int addrinfo_set_port(struct addrinfo *addr, int port)
+{
+ int rc = ARES_SUCCESS;
+ struct sockaddr_in *sockin = NULL;
+ struct sockaddr_in6 *sockin6 = NULL;
+
+ switch (addr->ai_family)
+ {
+ case AF_INET:
+ sockin = (struct sockaddr_in *) addr->ai_addr;
+ sockin->sin_port = (unsigned short)(port & 0xffff);
+ break;
+
+ case AF_INET6:
+ sockin6 = (struct sockaddr_in6 *) addr->ai_addr;
+ sockin6->sin6_port = (unsigned short)(port & 0xffff);
+ break;
+
+ default:
+ rc = ARES_EBADFAMILY;
+ break;
+ }
+
+ return rc;
+}
+
static int open_tcp_socket(ares_channel channel, struct server_state *server)
{
ares_socket_t s;
int opt;
- struct sockaddr_in sockin;
/* Acquire a socket. */
- s = socket(AF_INET, SOCK_STREAM, 0);
+ s = socket(server->addr->ai_family, SOCK_STREAM, 0);
if (s == ARES_SOCKET_BAD)
return -1;
@@ -923,12 +964,14 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
}
#endif
+ if (addrinfo_set_port(server->addr, channel->tcp_port) != ARES_SUCCESS)
+ {
+ sclose(s);
+ return -1;
+ }
+
/* Connect to the server. */
- memset(&sockin, 0, sizeof(sockin));
- sockin.sin_family = AF_INET;
- sockin.sin_addr = server->addr;
- sockin.sin_port = (unsigned short)(channel->tcp_port & 0xffff);
- if (connect(s, (struct sockaddr *) &sockin, sizeof(sockin)) == -1)
+ if (connect(s, server->addr->ai_addr, server->addr->ai_addrlen) == -1)
{
int err = SOCKERRNO;
@@ -960,10 +1003,9 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
static int open_udp_socket(ares_channel channel, struct server_state *server)
{
ares_socket_t s;
- struct sockaddr_in sockin;
/* Acquire a socket. */
- s = socket(AF_INET, SOCK_DGRAM, 0);
+ s = socket(server->addr->ai_family, SOCK_DGRAM, 0);
if (s == ARES_SOCKET_BAD)
return -1;
@@ -974,12 +1016,14 @@ static int open_udp_socket(ares_channel channel, struct server_state *server)
return -1;
}
+ if (addrinfo_set_port(server->addr, channel->udp_port) != ARES_SUCCESS)
+ {
+ sclose(s);
+ return -1;
+ }
+
/* Connect to the server. */
- memset(&sockin, 0, sizeof(sockin));
- sockin.sin_family = AF_INET;
- sockin.sin_addr = server->addr;
- sockin.sin_port = (unsigned short)(channel->udp_port & 0xffff);
- if (connect(s, (struct sockaddr *) &sockin, sizeof(sockin)) == -1)
+ if (connect(s, server->addr->ai_addr, server->addr->ai_addrlen) == -1)
{
int err = SOCKERRNO;