1968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
2968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Copyright 1998 by the Massachusetts Institute of Technology.
3968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *
4968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Permission to use, copy, modify, and distribute this
5968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software and its documentation for any purpose and without
6968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * fee is hereby granted, provided that the above copyright
7968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice appear in all copies and that both that copyright
8968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice and this permission notice appear in supporting
9968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * documentation, and that the name of M.I.T. not be used in
10968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * advertising or publicity pertaining to distribution of the
11968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software without specific, written prior permission.
12968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * M.I.T. makes no representations about the suitability of
13968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * this software for any purpose.  It is provided "as is"
14968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * without express or implied warranty.
15968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */
16968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
17968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_setup.h"
18968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
19968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_SOCKET_H
20968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <sys/socket.h>
21968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
22968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETINET_IN_H
23968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <netinet/in.h>
24968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
25968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_H
26968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <arpa/nameser.h>
27968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else
28968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include "nameser.h"
29968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
30968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_COMPAT_H
31968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <arpa/nameser_compat.h>
32968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
33968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
34968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <stdlib.h>
35968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <string.h>
36968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <time.h>
37968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares.h"
38968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_dns.h"
39968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_private.h"
40968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
41968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldvoid ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
42968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               ares_callback callback, void *arg)
43968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
44968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct query *query;
45968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int i;
46968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct timeval now;
47968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
48968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Verify that the query is at least long enough to hold the header. */
49968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (qlen < HFIXEDSZ || qlen >= (1 << 16))
50968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
51968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      callback(arg, ARES_EBADQUERY, 0, NULL, 0);
52968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      return;
53968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
54968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
55968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Allocate space for query and allocated fields. */
56968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query = malloc(sizeof(struct query));
57968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (!query)
58968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
59968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      callback(arg, ARES_ENOMEM, 0, NULL, 0);
60968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      return;
61968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
62968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->tcpbuf = malloc(qlen + 2);
63968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (!query->tcpbuf)
64968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
65968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      free(query);
66968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      callback(arg, ARES_ENOMEM, 0, NULL, 0);
67968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      return;
68968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
69968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->server_info = malloc(channel->nservers *
70968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                              sizeof(query->server_info[0]));
71968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (!query->server_info)
72968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
73968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      free(query->tcpbuf);
74968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      free(query);
75968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      callback(arg, ARES_ENOMEM, 0, NULL, 0);
76968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      return;
77968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
78968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
79968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Compute the query ID.  Start with no timeout. */
80968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->qid = (unsigned short)DNS_HEADER_QID(qbuf);
81968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->timeout.tv_sec = 0;
82968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->timeout.tv_usec = 0;
83968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
84968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Form the TCP query buffer by prepending qlen (as two
85968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * network-order bytes) to qbuf.
86968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
87968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->tcpbuf[0] = (unsigned char)((qlen >> 8) & 0xff);
88968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->tcpbuf[1] = (unsigned char)(qlen & 0xff);
89968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  memcpy(query->tcpbuf + 2, qbuf, qlen);
90968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->tcplen = qlen + 2;
91968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
92968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Fill in query arguments. */
93968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->qbuf = query->tcpbuf + 2;
94968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->qlen = qlen;
95968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->callback = callback;
96968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->arg = arg;
97968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
98968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Initialize query status. */
99968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->try_count = 0;
100968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
101968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Choose the server to send the query to. If rotation is enabled, keep track
102968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * of the next server we want to use. */
103968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->server = channel->last_server;
104968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (channel->rotate == 1)
105968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    channel->last_server = (channel->last_server + 1) % channel->nservers;
106968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
107968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  for (i = 0; i < channel->nservers; i++)
108968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
109968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      query->server_info[i].skip_server = 0;
110968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      query->server_info[i].tcp_connection_generation = 0;
111968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
112968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->using_tcp = (channel->flags & ARES_FLAG_USEVC) || qlen > PACKETSZ;
113968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->error_status = ARES_ECONNREFUSED;
114968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->timeouts = 0;
115968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
116968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Initialize our list nodes. */
117968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__init_list_node(&(query->queries_by_qid),     query);
118968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__init_list_node(&(query->queries_by_timeout), query);
119968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__init_list_node(&(query->queries_to_server),  query);
120968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__init_list_node(&(query->all_queries),        query);
121968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
122968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Chain the query into the list of all queries. */
123968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__insert_in_list(&(query->all_queries), &(channel->all_queries));
124968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Keep track of queries bucketed by qid, so we can process DNS
125968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * responses quickly.
126968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
127968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__insert_in_list(
128968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    &(query->queries_by_qid),
129968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    &(channel->queries_by_qid[query->qid % ARES_QID_TABLE_SIZE]));
130968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
131968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Perform the first query action. */
132968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  now = ares__tvnow();
133968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__send_query(channel, query, &now);
134968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
135