aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ares/ares.h4
-rw-r--r--ares/ares_init.c8
-rw-r--r--ares/ares_process.c55
3 files changed, 64 insertions, 3 deletions
diff --git a/ares/ares.h b/ares/ares.h
index 50ce7f850..03b6a924a 100644
--- a/ares/ares.h
+++ b/ares/ares.h
@@ -98,6 +98,8 @@ extern "C" {
#define ARES_OPT_LOOKUPS (1 << 8)
#define ARES_OPT_SOCK_STATE_CB (1 << 9)
#define ARES_OPT_SORTLIST (1 << 10)
+#define ARES_OPT_SOCK_SNDBUF (1 << 11)
+#define ARES_OPT_SOCK_RCVBUF (1 << 12)
/* Nameinfo flag values */
#define ARES_NI_NOFQDN (1 << 0)
@@ -177,6 +179,8 @@ struct ares_options {
int ndots;
unsigned short udp_port;
unsigned short tcp_port;
+ int socket_send_buffer_size;
+ int socket_receive_buffer_size;
struct in_addr *servers;
int nservers;
char **domains;
diff --git a/ares/ares_init.c b/ares/ares_init.c
index 298dd7b90..6c36d6e2b 100644
--- a/ares/ares_init.c
+++ b/ares/ares_init.c
@@ -133,6 +133,8 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
channel->ndots = -1;
channel->udp_port = -1;
channel->tcp_port = -1;
+ channel->socket_send_buffer_size = -1;
+ channel->socket_receive_buffer_size = -1;
channel->nservers = -1;
channel->ndomains = -1;
channel->nsort = -1;
@@ -320,6 +322,12 @@ static int init_by_options(ares_channel channel,
channel->sock_state_cb = options->sock_state_cb;
channel->sock_state_cb_data = options->sock_state_cb_data;
}
+ if ((optmask & ARES_OPT_SOCK_SNDBUF)
+ && channel->socket_send_buffer_size == -1)
+ channel->socket_send_buffer_size = options->socket_send_buffer_size;
+ if ((optmask & ARES_OPT_SOCK_RCVBUF)
+ && channel->socket_receive_buffer_size == -1)
+ channel->socket_receive_buffer_size = options->socket_receive_buffer_size;
/* Copy the servers, if given. */
if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
diff --git a/ares/ares_process.c b/ares/ares_process.c
index d359b115a..1db3d1129 100644
--- a/ares/ares_process.c
+++ b/ares/ares_process.c
@@ -25,6 +25,7 @@
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
+#include <netinet/tcp.h> /* for TCP_NODELAY */
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/nameser.h>
@@ -732,9 +733,36 @@ static int nonblock(ares_socket_t sockfd, /* operate on this */
#endif
}
+static int configure_socket(int s, ares_channel channel)
+{
+ nonblock(s, TRUE);
+
+#ifdef FD_CLOEXEC
+ /* Configure the socket fd as close-on-exec. */
+ if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1)
+ return -1;
+#endif
+
+ /* Set the socket's send and receive buffer sizes. */
+ if ((channel->socket_send_buffer_size > 0) &&
+ setsockopt(s, SOL_SOCKET, SO_SNDBUF,
+ &channel->socket_send_buffer_size,
+ sizeof(channel->socket_send_buffer_size)) == -1)
+ return -1;
+
+ if ((channel->socket_receive_buffer_size > 0) &&
+ setsockopt(s, SOL_SOCKET, SO_RCVBUF,
+ &channel->socket_receive_buffer_size,
+ sizeof(channel->socket_receive_buffer_size)) == -1)
+ return -1;
+
+ return 0;
+ }
+
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. */
@@ -742,8 +770,25 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
if (s == ARES_SOCKET_BAD)
return -1;
- /* Set the socket non-blocking. */
- nonblock(s, TRUE);
+ /* Configure it. */
+ if (configure_socket(s, channel) < 0)
+ {
+ close(s);
+ return -1;
+ }
+
+ /*
+ * Disable the Nagle algorithm (only relevant for TCP sockets, and thus not in
+ * configure_socket). In general, in DNS lookups we're pretty much interested
+ * in firing off a single request and then waiting for a reply, so batching
+ * isn't very interesting in general.
+ */
+ opt = 1;
+ if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) == -1)
+ {
+ close(s);
+ return -1;
+ }
/* Connect to the server. */
memset(&sockin, 0, sizeof(sockin));
@@ -777,7 +822,11 @@ static int open_udp_socket(ares_channel channel, struct server_state *server)
return -1;
/* Set the socket non-blocking. */
- nonblock(s, TRUE);
+ if (configure_socket(s, channel) < 0)
+ {
+ close(s);
+ return -1;
+ }
/* Connect to the server. */
memset(&sockin, 0, sizeof(sockin));