ares_create_query.c
Go to the documentation of this file.
1 
2 /* Copyright 1998 by the Massachusetts Institute of Technology.
3  *
4  * Permission to use, copy, modify, and distribute this
5  * software and its documentation for any purpose and without
6  * fee is hereby granted, provided that the above copyright
7  * notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting
9  * documentation, and that the name of M.I.T. not be used in
10  * advertising or publicity pertaining to distribution of the
11  * software without specific, written prior permission.
12  * M.I.T. makes no representations about the suitability of
13  * this software for any purpose. It is provided "as is"
14  * without express or implied warranty.
15  */
16 
17 #include "ares_setup.h"
18 
19 #ifdef HAVE_NETINET_IN_H
20 # include <netinet/in.h>
21 #endif
22 
23 #include "ares_nameser.h"
24 
25 #include "ares.h"
26 #include "ares_dns.h"
27 #include "ares_private.h"
28 
29 
30 /* Header format, from RFC 1035:
31  * 1 1 1 1 1 1
32  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
33  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
34  * | ID |
35  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
36  * |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
37  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
38  * | QDCOUNT |
39  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
40  * | ANCOUNT |
41  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
42  * | NSCOUNT |
43  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
44  * | ARCOUNT |
45  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
46  *
47  * AA, TC, RA, and RCODE are only set in responses. Brief description
48  * of the remaining fields:
49  * ID Identifier to match responses with queries
50  * QR Query (0) or response (1)
51  * Opcode For our purposes, always O_QUERY
52  * RD Recursion desired
53  * Z Reserved (zero)
54  * QDCOUNT Number of queries
55  * ANCOUNT Number of answers
56  * NSCOUNT Number of name server records
57  * ARCOUNT Number of additional records
58  *
59  * Question format, from RFC 1035:
60  * 1 1 1 1 1 1
61  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
62  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
63  * | |
64  * / QNAME /
65  * / /
66  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
67  * | QTYPE |
68  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
69  * | QCLASS |
70  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
71  *
72  * The query name is encoded as a series of labels, each represented
73  * as a one-byte length (maximum 63) followed by the text of the
74  * label. The list is terminated by a label of length zero (which can
75  * be thought of as the root domain).
76  */
77 
78 int ares_create_query(const char *name, int dnsclass, int type,
79  unsigned short id, int rd, unsigned char **bufp,
80  int *buflenp, int max_udp_size)
81 {
82  size_t len;
83  unsigned char *q;
84  const char *p;
85  size_t buflen;
86  unsigned char *buf;
87 
88  /* Set our results early, in case we bail out early with an error. */
89  *buflenp = 0;
90  *bufp = NULL;
91 
92  /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */
94  return ARES_ENOTFOUND;
95 
96  /* Allocate a memory area for the maximum size this packet might need. +2
97  * is for the length byte and zero termination if no dots or ecscaping is
98  * used.
99  */
100  len = strlen(name) + 2 + HFIXEDSZ + QFIXEDSZ +
101  (max_udp_size ? EDNSFIXEDSZ : 0);
102  buf = ares_malloc(len);
103  if (!buf)
104  return ARES_ENOMEM;
105 
106  /* Set up the header. */
107  q = buf;
108  memset(q, 0, HFIXEDSZ);
109  DNS_HEADER_SET_QID(q, id);
111  if (rd) {
112  DNS_HEADER_SET_RD(q, 1);
113  }
114  else {
115  DNS_HEADER_SET_RD(q, 0);
116  }
118 
119  if (max_udp_size) {
121  }
122 
123  /* A name of "." is a screw case for the loop below, so adjust it. */
124  if (strcmp(name, ".") == 0)
125  name++;
126 
127  /* Start writing out the name after the header. */
128  q += HFIXEDSZ;
129  while (*name)
130  {
131  if (*name == '.') {
132  ares_free (buf);
133  return ARES_EBADNAME;
134  }
135 
136  /* Count the number of bytes in this label. */
137  len = 0;
138  for (p = name; *p && *p != '.'; p++)
139  {
140  if (*p == '\\' && *(p + 1) != 0)
141  p++;
142  len++;
143  }
144  if (len > MAXLABEL) {
145  ares_free (buf);
146  return ARES_EBADNAME;
147  }
148 
149  /* Encode the length and copy the data. */
150  *q++ = (unsigned char)len;
151  for (p = name; *p && *p != '.'; p++)
152  {
153  if (*p == '\\' && *(p + 1) != 0)
154  p++;
155  *q++ = *p;
156  }
157 
158  /* Go to the next label and repeat, unless we hit the end. */
159  if (!*p)
160  break;
161  name = p + 1;
162  }
163 
164  /* Add the zero-length label at the end. */
165  *q++ = 0;
166 
167  /* Finish off the question with the type and class. */
169  DNS_QUESTION_SET_CLASS(q, dnsclass);
170 
171  q += QFIXEDSZ;
172  if (max_udp_size)
173  {
174  memset(q, 0, EDNSFIXEDSZ);
175  q++;
177  DNS_RR_SET_CLASS(q, max_udp_size);
178  q += (EDNSFIXEDSZ-1);
179  }
180  buflen = (q - buf);
181 
182  /* Reject names that are longer than the maximum of 255 bytes that's
183  * specified in RFC 1035 ("To simplify implementations, the total length of
184  * a domain name (i.e., label octets and label length octets) is restricted
185  * to 255 octets or less."). */
186  if (buflen > (size_t)(MAXCDNAME + HFIXEDSZ + QFIXEDSZ +
187  (max_udp_size ? EDNSFIXEDSZ : 0))) {
188  ares_free (buf);
189  return ARES_EBADNAME;
190  }
191 
192  /* we know this fits in an int at this point */
193  *buflenp = (int) buflen;
194  *bufp = buf;
195 
196  return ARES_SUCCESS;
197 }
DNS_HEADER_SET_ARCOUNT
#define DNS_HEADER_SET_ARCOUNT(h, v)
Definition: ares_dns.h:90
ARES_ENOMEM
#define ARES_ENOMEM
Definition: ares.h:117
memset
return memset(p, 0, total)
ares.h
EDNSFIXEDSZ
#define EDNSFIXEDSZ
Definition: ares_private.h:130
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
ares_dns.h
setup.name
name
Definition: setup.py:542
DNS_HEADER_SET_RD
#define DNS_HEADER_SET_RD(h, v)
Definition: ares_dns.h:83
ares__is_onion_domain
int ares__is_onion_domain(const char *name)
Definition: ares_getnameinfo.c:438
xds_manager.p
p
Definition: xds_manager.py:60
DNS_HEADER_SET_QID
#define DNS_HEADER_SET_QID(h, v)
Definition: ares_dns.h:78
ARES_ENOTFOUND
#define ARES_ENOTFOUND
Definition: ares.h:104
ares_create_query
int ares_create_query(const char *name, int dnsclass, int type, unsigned short id, int rd, unsigned char **bufp, int *buflenp, int max_udp_size)
Definition: ares_create_query.c:78
ares_malloc
void *(* ares_malloc)(size_t size)=default_malloc
Definition: ares_library_init.c:58
xds_interop_client.int
int
Definition: xds_interop_client.py:113
O_QUERY
#define O_QUERY
Definition: ares_nameser.h:225
MAXCDNAME
#define MAXCDNAME
Definition: ares_nameser.h:195
DNS_HEADER_SET_QDCOUNT
#define DNS_HEADER_SET_QDCOUNT(h, v)
Definition: ares_dns.h:87
ARES_EBADNAME
#define ARES_EBADNAME
Definition: ares.h:110
ARES_SUCCESS
#define ARES_SUCCESS
Definition: ares.h:98
DNS_QUESTION_SET_TYPE
#define DNS_QUESTION_SET_TYPE(q, v)
Definition: ares_dns.h:97
T_OPT
#define T_OPT
Definition: ares_nameser.h:430
ares_setup.h
DNS_QUESTION_SET_CLASS
#define DNS_QUESTION_SET_CLASS(q, v)
Definition: ares_dns.h:98
ares_free
void(* ares_free)(void *ptr)=default_free
Definition: ares_library_init.c:60
DNS_RR_SET_CLASS
#define DNS_RR_SET_CLASS(r, v)
Definition: ares_dns.h:108
ares_private.h
QFIXEDSZ
#define QFIXEDSZ
Definition: ares_nameser.h:207
HFIXEDSZ
#define HFIXEDSZ
Definition: ares_nameser.h:203
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
ares_nameser.h
DNS_RR_SET_TYPE
#define DNS_RR_SET_TYPE(r, v)
Definition: ares_dns.h:107
DNS_HEADER_SET_OPCODE
#define DNS_HEADER_SET_OPCODE(h, v)
Definition: ares_dns.h:80
MAXLABEL
#define MAXLABEL
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:5507


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:32