3 /* Copyright 1998 by the Massachusetts Institute of Technology.
5 * Permission to use, copy, modify, and distribute this
6 * software and its documentation for any purpose and without
7 * fee is hereby granted, provided that the above copyright
8 * notice appear in all copies and that both that copyright
9 * notice and this permission notice appear in supporting
10 * documentation, and that the name of M.I.T. not be used in
11 * advertising or publicity pertaining to distribution of the
12 * software without specific, written prior permission.
13 * M.I.T. makes no representations about the suitability of
14 * this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
19 #include <sys/types.h>
21 #if defined(WIN32) && !defined(WATT32)
24 #include <netinet/in.h>
25 #include <arpa/nameser.h>
26 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
27 #include <arpa/nameser_compat.h>
35 #include "ares_private.h"
37 /* Header format, from RFC 1035:
39 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
40 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
42 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
43 * |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
44 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
46 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
48 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
50 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
52 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
54 * AA, TC, RA, and RCODE are only set in responses. Brief description
55 * of the remaining fields:
56 * ID Identifier to match responses with queries
57 * QR Query (0) or response (1)
58 * Opcode For our purposes, always QUERY
59 * RD Recursion desired
61 * QDCOUNT Number of queries
62 * ANCOUNT Number of answers
63 * NSCOUNT Number of name server records
64 * ARCOUNT Number of additional records
66 * Question format, from RFC 1035:
68 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
69 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
73 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
75 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
77 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
79 * The query name is encoded as a series of labels, each represented
80 * as a one-byte length (maximum 63) followed by the text of the
81 * label. The list is terminated by a label of length zero (which can
82 * be thought of as the root domain).
85 int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id,
86 int rd, unsigned char **buf, int *buflen)
92 /* Compute the length of the encoded name so we can check buflen.
93 * Start counting at 1 for the zero-length label at the end. */
95 for (p = name; *p; p++)
97 if (*p == '\\' && *(p + 1) != 0)
101 /* If there are n periods in the name, there are n + 1 labels, and
102 * thus n + 1 length fields, unless the name is empty or ends with a
103 * period. So add 1 unless name is empty or ends with a period.
105 if (*name && *(p - 1) != '.')
108 *buflen = len + HFIXEDSZ + QFIXEDSZ;
109 *buf = malloc(*buflen);
113 /* Set up the header. */
115 memset(q, 0, HFIXEDSZ);
116 DNS_HEADER_SET_QID(q, id);
117 DNS_HEADER_SET_OPCODE(q, QUERY);
118 DNS_HEADER_SET_RD(q, (rd) ? 1 : 0);
119 DNS_HEADER_SET_QDCOUNT(q, 1);
121 /* A name of "." is a screw case for the loop below, so adjust it. */
122 if (strcmp(name, ".") == 0)
125 /* Start writing out the name after the header. */
130 return ARES_EBADNAME;
132 /* Count the number of bytes in this label. */
134 for (p = name; *p && *p != '.'; p++)
136 if (*p == '\\' && *(p + 1) != 0)
141 return ARES_EBADNAME;
143 /* Encode the length and copy the data. */
144 *q++ = (unsigned char)len;
145 for (p = name; *p && *p != '.'; p++)
147 if (*p == '\\' && *(p + 1) != 0)
152 /* Go to the next label and repeat, unless we hit the end. */
158 /* Add the zero-length label at the end. */
161 /* Finish off the question with the type and class. */
162 DNS_QUESTION_SET_TYPE(q, type);
163 DNS_QUESTION_SET_CLASS(q, dnsclass);