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 "ares.h"
37968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_dns.h"
38968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_private.h"
39968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
40968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Header format, from RFC 1035:
41968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *                                  1  1  1  1  1  1
42968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
43968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
44968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  |                      ID                       |
45968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
46968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
47968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
48968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  |                    QDCOUNT                    |
49968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
50968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  |                    ANCOUNT                    |
51968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
52968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  |                    NSCOUNT                    |
53968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
54968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  |                    ARCOUNT                    |
55968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
56968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *
57968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * AA, TC, RA, and RCODE are only set in responses.  Brief description
58968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * of the remaining fields:
59968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *      ID      Identifier to match responses with queries
60968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *      QR      Query (0) or response (1)
61968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *      Opcode  For our purposes, always QUERY
62968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *      RD      Recursion desired
63968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *      Z       Reserved (zero)
64968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *      QDCOUNT Number of queries
65968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *      ANCOUNT Number of answers
66968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *      NSCOUNT Number of name server records
67968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *      ARCOUNT Number of additional records
68968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *
69968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Question format, from RFC 1035:
70968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *                                  1  1  1  1  1  1
71968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
72968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
73968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  |                                               |
74968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  /                     QNAME                     /
75968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  /                                               /
76968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
77968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  |                     QTYPE                     |
78968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
79968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  |                     QCLASS                    |
80968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
81968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *
82968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * The query name is encoded as a series of labels, each represented
83968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * as a one-byte length (maximum 63) followed by the text of the
84968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * label.  The list is terminated by a label of length zero (which can
85968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * be thought of as the root domain).
86968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */
87968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
88968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldint ares_mkquery(const char *name, int dnsclass, int type, unsigned short id,
89968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 int rd, unsigned char **buf, int *buflen)
90968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
91968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int len;
92968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  unsigned char *q;
93968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  const char *p;
94968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
95968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Set our results early, in case we bail out early with an error. */
96968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  *buflen = 0;
97968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  *buf = NULL;
98968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
99968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Compute the length of the encoded name so we can check buflen.
100968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * Start counting at 1 for the zero-length label at the end. */
101968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  len = 1;
102968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  for (p = name; *p; p++)
103968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
104968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (*p == '\\' && *(p + 1) != 0)
105968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        p++;
106968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      len++;
107968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
108968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* If there are n periods in the name, there are n + 1 labels, and
109968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * thus n + 1 length fields, unless the name is empty or ends with a
110968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * period.  So add 1 unless name is empty or ends with a period.
111968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
112968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (*name && *(p - 1) != '.')
113968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    len++;
114968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
115968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Immediately reject names that are longer than the maximum of 255
116968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * bytes that's specified in RFC 1035 ("To simplify implementations,
117968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * the total length of a domain name (i.e., label octets and label
118968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * length octets) is restricted to 255 octets or less."). We aren't
119968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * doing this just to be a stickler about RFCs. For names that are
120968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * too long, 'dnscache' closes its TCP connection to us immediately
121968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * (when using TCP) and ignores the request when using UDP, and
122968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * BIND's named returns ServFail (TCP or UDP). Sending a request
123968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * that we know will cause 'dnscache' to close the TCP connection is
124968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * painful, since that makes any other outstanding requests on that
125968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * connection fail. And sending a UDP request that we know
126968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * 'dnscache' will ignore is bad because resources will be tied up
127968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * until we time-out the request.
128968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
129968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (len > MAXCDNAME)
130968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return ARES_EBADNAME;
131968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
132968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  *buflen = len + HFIXEDSZ + QFIXEDSZ;
133968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  *buf = malloc(*buflen);
134968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (!*buf)
135968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      return ARES_ENOMEM;
136968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
137968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Set up the header. */
138968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  q = *buf;
139968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  memset(q, 0, HFIXEDSZ);
140968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  DNS_HEADER_SET_QID(q, id);
141968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  DNS_HEADER_SET_OPCODE(q, QUERY);
142968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (rd) {
143968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    DNS_HEADER_SET_RD(q, 1);
144968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  }
145968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  else {
146968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    DNS_HEADER_SET_RD(q, 0);
147968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  }
148968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  DNS_HEADER_SET_QDCOUNT(q, 1);
149968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
150968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* A name of "." is a screw case for the loop below, so adjust it. */
151968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (strcmp(name, ".") == 0)
152968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    name++;
153968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
154968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Start writing out the name after the header. */
155968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  q += HFIXEDSZ;
156968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  while (*name)
157968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
158968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (*name == '.')
159968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        return ARES_EBADNAME;
160968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
161968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Count the number of bytes in this label. */
162968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      len = 0;
163968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      for (p = name; *p && *p != '.'; p++)
164968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
165968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (*p == '\\' && *(p + 1) != 0)
166968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            p++;
167968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          len++;
168968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
169968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (len > MAXLABEL)
170968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        return ARES_EBADNAME;
171968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
172968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Encode the length and copy the data. */
173968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      *q++ = (unsigned char)len;
174968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      for (p = name; *p && *p != '.'; p++)
175968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
176968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (*p == '\\' && *(p + 1) != 0)
177968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            p++;
178968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          *q++ = *p;
179968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
180968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
181968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Go to the next label and repeat, unless we hit the end. */
182968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (!*p)
183968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        break;
184968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      name = p + 1;
185968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
186968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
187968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Add the zero-length label at the end. */
188968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  *q++ = 0;
189968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
190968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Finish off the question with the type and class. */
191968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  DNS_QUESTION_SET_TYPE(q, type);
192968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  DNS_QUESTION_SET_CLASS(q, dnsclass);
193968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
194968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return ARES_SUCCESS;
195968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
196