summaryrefslogtreecommitdiff
path: root/ares_send.c
diff options
context:
space:
mode:
Diffstat (limited to 'ares_send.c')
-rw-r--r--ares_send.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/ares_send.c b/ares_send.c
new file mode 100644
index 0000000..b17b912
--- /dev/null
+++ b/ares_send.c
@@ -0,0 +1,104 @@
+/* Copyright 1998 by the Massachusetts Institute of Technology.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ */
+
+static const char rcsid[] = "$Id$";
+
+#include <sys/types.h>
+
+#ifdef WIN32
+#include "nameser.h"
+#else
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "ares.h"
+#include "ares_dns.h"
+#include "ares_private.h"
+
+void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
+ ares_callback callback, void *arg)
+{
+ struct query *query;
+ int i;
+ time_t now;
+
+ /* Verify that the query is at least long enough to hold the header. */
+ if (qlen < HFIXEDSZ || qlen >= (1 << 16))
+ {
+ callback(arg, ARES_EBADQUERY, NULL, 0);
+ return;
+ }
+
+ /* Allocate space for query and allocated fields. */
+ query = malloc(sizeof(struct query));
+ if (!query)
+ {
+ callback(arg, ARES_ENOMEM, NULL, 0);
+ return;
+ }
+ query->tcpbuf = malloc(qlen + 2);
+ if (!query->tcpbuf)
+ {
+ free(query);
+ callback(arg, ARES_ENOMEM, NULL, 0);
+ return;
+ }
+ query->skip_server = malloc(channel->nservers * sizeof(int));
+ if (!query->skip_server)
+ {
+ free(query->tcpbuf);
+ free(query);
+ callback(arg, ARES_ENOMEM, NULL, 0);
+ return;
+ }
+
+ /* Compute the query ID. Start with no timeout. */
+ query->qid = DNS_HEADER_QID(qbuf);
+ query->timeout = 0;
+
+ /* Form the TCP query buffer by prepending qlen (as two
+ * network-order bytes) to qbuf.
+ */
+ query->tcpbuf[0] = (qlen >> 8) & 0xff;
+ query->tcpbuf[1] = qlen & 0xff;
+ memcpy(query->tcpbuf + 2, qbuf, qlen);
+ query->tcplen = qlen + 2;
+
+ /* Fill in query arguments. */
+ query->qbuf = query->tcpbuf + 2;
+ query->qlen = qlen;
+ query->callback = callback;
+ query->arg = arg;
+
+ /* Initialize query status. */
+ query->try = 0;
+ query->server = 0;
+ for (i = 0; i < channel->nservers; i++)
+ query->skip_server[i] = 0;
+ query->using_tcp = (channel->flags & ARES_FLAG_USEVC) || qlen > PACKETSZ;
+ query->error_status = ARES_ECONNREFUSED;
+
+ /* Chain the query into this channel's query list. */
+ query->next = channel->queries;
+ channel->queries = query;
+
+ /* Perform the first query action. */
+ time(&now);
+ ares__send_query(channel, query, now);
+}