1 /* MIT License
2 *
3 * Copyright (c) 2023 Brad House
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * SPDX-License-Identifier: MIT
25 */
26 #include "ares_private.h"
27 #include <limits.h>
28 #ifdef HAVE_STDINT_H
29 # include <stdint.h>
30 #endif
31
ares_dns_rr_remaining_len(const ares_buf_t * buf,size_t orig_len,size_t rdlength)32 static size_t ares_dns_rr_remaining_len(const ares_buf_t *buf, size_t orig_len,
33 size_t rdlength)
34 {
35 size_t used_len = orig_len - ares_buf_len(buf);
36 if (used_len >= rdlength) {
37 return 0;
38 }
39 return rdlength - used_len;
40 }
41
ares_dns_parse_and_set_dns_name(ares_buf_t * buf,ares_bool_t is_hostname,ares_dns_rr_t * rr,ares_dns_rr_key_t key)42 static ares_status_t ares_dns_parse_and_set_dns_name(ares_buf_t *buf,
43 ares_bool_t is_hostname,
44 ares_dns_rr_t *rr,
45 ares_dns_rr_key_t key)
46 {
47 ares_status_t status;
48 char *name = NULL;
49
50 status = ares_dns_name_parse(buf, &name, is_hostname);
51 if (status != ARES_SUCCESS) {
52 return status;
53 }
54
55 status = ares_dns_rr_set_str_own(rr, key, name);
56 if (status != ARES_SUCCESS) {
57 ares_free(name);
58 return status;
59 }
60 return ARES_SUCCESS;
61 }
62
ares_dns_parse_and_set_dns_str(ares_buf_t * buf,size_t max_len,ares_dns_rr_t * rr,ares_dns_rr_key_t key,ares_bool_t blank_allowed)63 static ares_status_t ares_dns_parse_and_set_dns_str(ares_buf_t *buf,
64 size_t max_len,
65 ares_dns_rr_t *rr,
66 ares_dns_rr_key_t key,
67 ares_bool_t blank_allowed)
68 {
69 ares_status_t status;
70 char *str = NULL;
71
72 status = ares_buf_parse_dns_str(buf, max_len, &str);
73 if (status != ARES_SUCCESS) {
74 return status;
75 }
76
77 if (!blank_allowed && ares_strlen(str) == 0) {
78 ares_free(str);
79 return ARES_EBADRESP;
80 }
81
82 status = ares_dns_rr_set_str_own(rr, key, str);
83 if (status != ARES_SUCCESS) {
84 ares_free(str);
85 return status;
86 }
87 return ARES_SUCCESS;
88 }
89
90 static ares_status_t
ares_dns_parse_and_set_dns_abin(ares_buf_t * buf,size_t max_len,ares_dns_rr_t * rr,ares_dns_rr_key_t key,ares_bool_t validate_printable)91 ares_dns_parse_and_set_dns_abin(ares_buf_t *buf, size_t max_len,
92 ares_dns_rr_t *rr, ares_dns_rr_key_t key,
93 ares_bool_t validate_printable)
94 {
95 ares_status_t status;
96 ares_dns_multistring_t *strs = NULL;
97
98 status =
99 ares_dns_multistring_parse_buf(buf, max_len, &strs, validate_printable);
100 if (status != ARES_SUCCESS) {
101 return status;
102 }
103
104 status = ares_dns_rr_set_abin_own(rr, key, strs);
105 if (status != ARES_SUCCESS) {
106 ares_dns_multistring_destroy(strs);
107 return status;
108 }
109 return ARES_SUCCESS;
110 }
111
ares_dns_parse_and_set_be32(ares_buf_t * buf,ares_dns_rr_t * rr,ares_dns_rr_key_t key)112 static ares_status_t ares_dns_parse_and_set_be32(ares_buf_t *buf,
113 ares_dns_rr_t *rr,
114 ares_dns_rr_key_t key)
115 {
116 ares_status_t status;
117 unsigned int u32;
118
119 status = ares_buf_fetch_be32(buf, &u32);
120 if (status != ARES_SUCCESS) {
121 return status;
122 }
123
124 return ares_dns_rr_set_u32(rr, key, u32);
125 }
126
ares_dns_parse_and_set_be16(ares_buf_t * buf,ares_dns_rr_t * rr,ares_dns_rr_key_t key)127 static ares_status_t ares_dns_parse_and_set_be16(ares_buf_t *buf,
128 ares_dns_rr_t *rr,
129 ares_dns_rr_key_t key)
130 {
131 ares_status_t status;
132 unsigned short u16;
133
134 status = ares_buf_fetch_be16(buf, &u16);
135 if (status != ARES_SUCCESS) {
136 return status;
137 }
138
139 return ares_dns_rr_set_u16(rr, key, u16);
140 }
141
ares_dns_parse_and_set_u8(ares_buf_t * buf,ares_dns_rr_t * rr,ares_dns_rr_key_t key)142 static ares_status_t ares_dns_parse_and_set_u8(ares_buf_t *buf,
143 ares_dns_rr_t *rr,
144 ares_dns_rr_key_t key)
145 {
146 ares_status_t status;
147 unsigned char u8;
148
149 status = ares_buf_fetch_bytes(buf, &u8, 1);
150 if (status != ARES_SUCCESS) {
151 return status;
152 }
153
154 return ares_dns_rr_set_u8(rr, key, u8);
155 }
156
ares_dns_parse_rr_a(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)157 static ares_status_t ares_dns_parse_rr_a(ares_buf_t *buf, ares_dns_rr_t *rr,
158 size_t rdlength)
159 {
160 struct in_addr addr;
161 ares_status_t status;
162
163 (void)rdlength; /* Not needed */
164
165 status = ares_buf_fetch_bytes(buf, (unsigned char *)&addr, sizeof(addr));
166 if (status != ARES_SUCCESS) {
167 return status;
168 }
169
170 return ares_dns_rr_set_addr(rr, ARES_RR_A_ADDR, &addr);
171 }
172
ares_dns_parse_rr_ns(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)173 static ares_status_t ares_dns_parse_rr_ns(ares_buf_t *buf, ares_dns_rr_t *rr,
174 size_t rdlength)
175 {
176 (void)rdlength; /* Not needed */
177
178 return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
179 ARES_RR_NS_NSDNAME);
180 }
181
ares_dns_parse_rr_cname(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)182 static ares_status_t ares_dns_parse_rr_cname(ares_buf_t *buf, ares_dns_rr_t *rr,
183 size_t rdlength)
184 {
185 (void)rdlength; /* Not needed */
186
187 return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
188 ARES_RR_CNAME_CNAME);
189 }
190
ares_dns_parse_rr_soa(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)191 static ares_status_t ares_dns_parse_rr_soa(ares_buf_t *buf, ares_dns_rr_t *rr,
192 size_t rdlength)
193 {
194 ares_status_t status;
195
196 (void)rdlength; /* Not needed */
197
198 /* MNAME */
199 status =
200 ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_SOA_MNAME);
201 if (status != ARES_SUCCESS) {
202 return status;
203 }
204
205 /* RNAME */
206 status =
207 ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_SOA_RNAME);
208 if (status != ARES_SUCCESS) {
209 return status;
210 }
211
212 /* SERIAL */
213 status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_SERIAL);
214 if (status != ARES_SUCCESS) {
215 return status;
216 }
217
218 /* REFRESH */
219 status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_REFRESH);
220 if (status != ARES_SUCCESS) {
221 return status;
222 }
223
224 /* RETRY */
225 status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_RETRY);
226 if (status != ARES_SUCCESS) {
227 return status;
228 }
229
230 /* EXPIRE */
231 status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_EXPIRE);
232 if (status != ARES_SUCCESS) {
233 return status;
234 }
235
236 /* MINIMUM */
237 return ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_MINIMUM);
238 }
239
ares_dns_parse_rr_ptr(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)240 static ares_status_t ares_dns_parse_rr_ptr(ares_buf_t *buf, ares_dns_rr_t *rr,
241 size_t rdlength)
242 {
243 (void)rdlength; /* Not needed */
244
245 return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
246 ARES_RR_PTR_DNAME);
247 }
248
ares_dns_parse_rr_hinfo(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)249 static ares_status_t ares_dns_parse_rr_hinfo(ares_buf_t *buf, ares_dns_rr_t *rr,
250 size_t rdlength)
251 {
252 ares_status_t status;
253 size_t orig_len = ares_buf_len(buf);
254
255 (void)rdlength; /* Not needed */
256
257 /* CPU */
258 status = ares_dns_parse_and_set_dns_str(
259 buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
260 ARES_RR_HINFO_CPU, ARES_TRUE);
261 if (status != ARES_SUCCESS) {
262 return status;
263 }
264
265 /* OS */
266 status = ares_dns_parse_and_set_dns_str(
267 buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
268 ARES_RR_HINFO_OS, ARES_TRUE);
269
270 return status;
271 }
272
ares_dns_parse_rr_mx(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)273 static ares_status_t ares_dns_parse_rr_mx(ares_buf_t *buf, ares_dns_rr_t *rr,
274 size_t rdlength)
275 {
276 ares_status_t status;
277
278 (void)rdlength; /* Not needed */
279
280 /* PREFERENCE */
281 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_MX_PREFERENCE);
282 if (status != ARES_SUCCESS) {
283 return status;
284 }
285
286 /* EXCHANGE */
287 return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
288 ARES_RR_MX_EXCHANGE);
289 }
290
ares_dns_parse_rr_txt(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)291 static ares_status_t ares_dns_parse_rr_txt(ares_buf_t *buf, ares_dns_rr_t *rr,
292 size_t rdlength)
293 {
294 return ares_dns_parse_and_set_dns_abin(buf, rdlength, rr, ARES_RR_TXT_DATA,
295 ARES_FALSE);
296 }
297
ares_dns_parse_rr_sig(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)298 static ares_status_t ares_dns_parse_rr_sig(ares_buf_t *buf, ares_dns_rr_t *rr,
299 size_t rdlength)
300 {
301 ares_status_t status;
302 size_t orig_len = ares_buf_len(buf);
303 size_t len;
304 unsigned char *data;
305
306 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SIG_TYPE_COVERED);
307 if (status != ARES_SUCCESS) {
308 return status;
309 }
310
311 status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_SIG_ALGORITHM);
312 if (status != ARES_SUCCESS) {
313 return status;
314 }
315
316 status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_SIG_LABELS);
317 if (status != ARES_SUCCESS) {
318 return status;
319 }
320
321 status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SIG_ORIGINAL_TTL);
322 if (status != ARES_SUCCESS) {
323 return status;
324 }
325
326 status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SIG_EXPIRATION);
327 if (status != ARES_SUCCESS) {
328 return status;
329 }
330
331 status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SIG_INCEPTION);
332 if (status != ARES_SUCCESS) {
333 return status;
334 }
335
336 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SIG_KEY_TAG);
337 if (status != ARES_SUCCESS) {
338 return status;
339 }
340
341 status = ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
342 ARES_RR_SIG_SIGNERS_NAME);
343 if (status != ARES_SUCCESS) {
344 return status;
345 }
346
347 len = ares_dns_rr_remaining_len(buf, orig_len, rdlength);
348 if (len == 0) {
349 return ARES_EBADRESP;
350 }
351
352 status = ares_buf_fetch_bytes_dup(buf, len, ARES_FALSE, &data);
353 if (status != ARES_SUCCESS) {
354 return status;
355 }
356
357 status = ares_dns_rr_set_bin_own(rr, ARES_RR_SIG_SIGNATURE, data, len);
358 if (status != ARES_SUCCESS) {
359 ares_free(data);
360 return status;
361 }
362
363 return ARES_SUCCESS;
364 }
365
ares_dns_parse_rr_aaaa(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)366 static ares_status_t ares_dns_parse_rr_aaaa(ares_buf_t *buf, ares_dns_rr_t *rr,
367 size_t rdlength)
368 {
369 struct ares_in6_addr addr;
370 ares_status_t status;
371
372 (void)rdlength; /* Not needed */
373
374 status = ares_buf_fetch_bytes(buf, (unsigned char *)&addr, sizeof(addr));
375 if (status != ARES_SUCCESS) {
376 return status;
377 }
378
379 return ares_dns_rr_set_addr6(rr, ARES_RR_AAAA_ADDR, &addr);
380 }
381
ares_dns_parse_rr_srv(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)382 static ares_status_t ares_dns_parse_rr_srv(ares_buf_t *buf, ares_dns_rr_t *rr,
383 size_t rdlength)
384 {
385 ares_status_t status;
386
387 (void)rdlength; /* Not needed */
388
389 /* PRIORITY */
390 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SRV_PRIORITY);
391 if (status != ARES_SUCCESS) {
392 return status;
393 }
394
395 /* WEIGHT */
396 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SRV_WEIGHT);
397 if (status != ARES_SUCCESS) {
398 return status;
399 }
400
401 /* PORT */
402 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SRV_PORT);
403 if (status != ARES_SUCCESS) {
404 return status;
405 }
406
407 /* TARGET */
408 return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
409 ARES_RR_SRV_TARGET);
410 }
411
ares_dns_parse_rr_naptr(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)412 static ares_status_t ares_dns_parse_rr_naptr(ares_buf_t *buf, ares_dns_rr_t *rr,
413 size_t rdlength)
414 {
415 ares_status_t status;
416 size_t orig_len = ares_buf_len(buf);
417
418 /* ORDER */
419 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_NAPTR_ORDER);
420 if (status != ARES_SUCCESS) {
421 return status;
422 }
423
424 /* PREFERENCE */
425 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_NAPTR_PREFERENCE);
426 if (status != ARES_SUCCESS) {
427 return status;
428 }
429
430 /* FLAGS */
431 status = ares_dns_parse_and_set_dns_str(
432 buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
433 ARES_RR_NAPTR_FLAGS, ARES_TRUE);
434 if (status != ARES_SUCCESS) {
435 return status;
436 }
437
438 /* SERVICES */
439 status = ares_dns_parse_and_set_dns_str(
440 buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
441 ARES_RR_NAPTR_SERVICES, ARES_TRUE);
442 if (status != ARES_SUCCESS) {
443 return status;
444 }
445
446 /* REGEXP */
447 status = ares_dns_parse_and_set_dns_str(
448 buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
449 ARES_RR_NAPTR_REGEXP, ARES_TRUE);
450 if (status != ARES_SUCCESS) {
451 return status;
452 }
453
454 /* REPLACEMENT */
455 return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
456 ARES_RR_NAPTR_REPLACEMENT);
457 }
458
ares_dns_parse_rr_opt(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength,unsigned short raw_class,unsigned int raw_ttl)459 static ares_status_t ares_dns_parse_rr_opt(ares_buf_t *buf, ares_dns_rr_t *rr,
460 size_t rdlength,
461 unsigned short raw_class,
462 unsigned int raw_ttl)
463 {
464 ares_status_t status;
465 size_t orig_len = ares_buf_len(buf);
466 unsigned short rcode_high;
467
468 status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_UDP_SIZE, raw_class);
469 if (status != ARES_SUCCESS) {
470 return status;
471 }
472
473 /* First 8 bits of TTL are an extended RCODE, and they go in the higher order
474 * after the original 4-bit rcode */
475 rcode_high = (unsigned short)((raw_ttl >> 20) & 0x0FF0);
476 rr->parent->raw_rcode |= rcode_high;
477
478 status = ares_dns_rr_set_u8(rr, ARES_RR_OPT_VERSION,
479 (unsigned char)(raw_ttl >> 16) & 0xFF);
480 if (status != ARES_SUCCESS) {
481 return status;
482 }
483
484 status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_FLAGS,
485 (unsigned short)(raw_ttl & 0xFFFF));
486 if (status != ARES_SUCCESS) {
487 return status;
488 }
489
490 /* Parse options */
491 while (ares_dns_rr_remaining_len(buf, orig_len, rdlength)) {
492 unsigned short opt = 0;
493 unsigned short len = 0;
494 unsigned char *val = NULL;
495
496 /* Fetch be16 option */
497 status = ares_buf_fetch_be16(buf, &opt);
498 if (status != ARES_SUCCESS) {
499 return status;
500 }
501
502 /* Fetch be16 length */
503 status = ares_buf_fetch_be16(buf, &len);
504 if (status != ARES_SUCCESS) {
505 return status;
506 }
507
508 if (len) {
509 status = ares_buf_fetch_bytes_dup(buf, len, ARES_TRUE, &val);
510 if (status != ARES_SUCCESS) {
511 return status;
512 }
513 }
514
515 status = ares_dns_rr_set_opt_own(rr, ARES_RR_OPT_OPTIONS, opt, val, len);
516 if (status != ARES_SUCCESS) {
517 return status;
518 }
519 }
520
521 return ARES_SUCCESS;
522 }
523
ares_dns_parse_rr_tlsa(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)524 static ares_status_t ares_dns_parse_rr_tlsa(ares_buf_t *buf, ares_dns_rr_t *rr,
525 size_t rdlength)
526 {
527 ares_status_t status;
528 size_t orig_len = ares_buf_len(buf);
529 size_t len;
530 unsigned char *data;
531
532 status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_TLSA_CERT_USAGE);
533 if (status != ARES_SUCCESS) {
534 return status;
535 }
536
537 status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_TLSA_SELECTOR);
538 if (status != ARES_SUCCESS) {
539 return status;
540 }
541
542 status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_TLSA_MATCH);
543 if (status != ARES_SUCCESS) {
544 return status;
545 }
546
547 len = ares_dns_rr_remaining_len(buf, orig_len, rdlength);
548 if (len == 0) {
549 return ARES_EBADRESP;
550 }
551
552 status = ares_buf_fetch_bytes_dup(buf, len, ARES_FALSE, &data);
553 if (status != ARES_SUCCESS) {
554 return status;
555 }
556
557 status = ares_dns_rr_set_bin_own(rr, ARES_RR_TLSA_DATA, data, len);
558 if (status != ARES_SUCCESS) {
559 ares_free(data);
560 return status;
561 }
562
563 return ARES_SUCCESS;
564 }
565
ares_dns_parse_rr_svcb(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)566 static ares_status_t ares_dns_parse_rr_svcb(ares_buf_t *buf, ares_dns_rr_t *rr,
567 size_t rdlength)
568 {
569 ares_status_t status;
570 size_t orig_len = ares_buf_len(buf);
571
572 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SVCB_PRIORITY);
573 if (status != ARES_SUCCESS) {
574 return status;
575 }
576
577 status =
578 ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_SVCB_TARGET);
579 if (status != ARES_SUCCESS) {
580 return status;
581 }
582
583 /* Parse params */
584 while (ares_dns_rr_remaining_len(buf, orig_len, rdlength)) {
585 unsigned short opt = 0;
586 unsigned short len = 0;
587 unsigned char *val = NULL;
588
589 /* Fetch be16 option */
590 status = ares_buf_fetch_be16(buf, &opt);
591 if (status != ARES_SUCCESS) {
592 return status;
593 }
594
595 /* Fetch be16 length */
596 status = ares_buf_fetch_be16(buf, &len);
597 if (status != ARES_SUCCESS) {
598 return status;
599 }
600
601 if (len) {
602 status = ares_buf_fetch_bytes_dup(buf, len, ARES_TRUE, &val);
603 if (status != ARES_SUCCESS) {
604 return status;
605 }
606 }
607
608 status = ares_dns_rr_set_opt_own(rr, ARES_RR_SVCB_PARAMS, opt, val, len);
609 if (status != ARES_SUCCESS) {
610 return status;
611 }
612 }
613
614 return ARES_SUCCESS;
615 }
616
ares_dns_parse_rr_https(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)617 static ares_status_t ares_dns_parse_rr_https(ares_buf_t *buf, ares_dns_rr_t *rr,
618 size_t rdlength)
619 {
620 ares_status_t status;
621 size_t orig_len = ares_buf_len(buf);
622
623 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_HTTPS_PRIORITY);
624 if (status != ARES_SUCCESS) {
625 return status;
626 }
627
628 status =
629 ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_HTTPS_TARGET);
630 if (status != ARES_SUCCESS) {
631 return status;
632 }
633
634 /* Parse params */
635 while (ares_dns_rr_remaining_len(buf, orig_len, rdlength)) {
636 unsigned short opt = 0;
637 unsigned short len = 0;
638 unsigned char *val = NULL;
639
640 /* Fetch be16 option */
641 status = ares_buf_fetch_be16(buf, &opt);
642 if (status != ARES_SUCCESS) {
643 return status;
644 }
645
646 /* Fetch be16 length */
647 status = ares_buf_fetch_be16(buf, &len);
648 if (status != ARES_SUCCESS) {
649 return status;
650 }
651
652 if (len) {
653 status = ares_buf_fetch_bytes_dup(buf, len, ARES_TRUE, &val);
654 if (status != ARES_SUCCESS) {
655 return status;
656 }
657 }
658
659 status = ares_dns_rr_set_opt_own(rr, ARES_RR_HTTPS_PARAMS, opt, val, len);
660 if (status != ARES_SUCCESS) {
661 return status;
662 }
663 }
664
665 return ARES_SUCCESS;
666 }
667
ares_dns_parse_rr_uri(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)668 static ares_status_t ares_dns_parse_rr_uri(ares_buf_t *buf, ares_dns_rr_t *rr,
669 size_t rdlength)
670 {
671 char *name = NULL;
672 ares_status_t status;
673 size_t orig_len = ares_buf_len(buf);
674 size_t remaining_len;
675
676 /* PRIORITY */
677 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_URI_PRIORITY);
678 if (status != ARES_SUCCESS) {
679 return status;
680 }
681
682 /* WEIGHT */
683 status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_URI_WEIGHT);
684 if (status != ARES_SUCCESS) {
685 return status;
686 }
687
688 /* TARGET -- not in string format, rest of buffer, required to be
689 * non-zero length */
690 remaining_len = ares_dns_rr_remaining_len(buf, orig_len, rdlength);
691 if (remaining_len == 0) {
692 status = ARES_EBADRESP;
693 return status;
694 }
695
696 /* NOTE: Not in DNS string format */
697 status = ares_buf_fetch_str_dup(buf, remaining_len, &name);
698 if (status != ARES_SUCCESS) {
699 return status;
700 }
701
702 if (!ares_str_isprint(name, remaining_len)) {
703 ares_free(name);
704 return ARES_EBADRESP;
705 }
706
707 status = ares_dns_rr_set_str_own(rr, ARES_RR_URI_TARGET, name);
708 if (status != ARES_SUCCESS) {
709 ares_free(name);
710 return status;
711 }
712 name = NULL;
713
714 return ARES_SUCCESS;
715 }
716
ares_dns_parse_rr_caa(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength)717 static ares_status_t ares_dns_parse_rr_caa(ares_buf_t *buf, ares_dns_rr_t *rr,
718 size_t rdlength)
719 {
720 unsigned char *data = NULL;
721 size_t data_len = 0;
722 ares_status_t status;
723 size_t orig_len = ares_buf_len(buf);
724
725 /* CRITICAL */
726 status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_CAA_CRITICAL);
727 if (status != ARES_SUCCESS) {
728 return status;
729 }
730
731 /* Tag */
732 status = ares_dns_parse_and_set_dns_str(
733 buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
734 ARES_RR_CAA_TAG, ARES_FALSE);
735 if (status != ARES_SUCCESS) {
736 return status;
737 }
738
739 /* Value - binary! (remaining buffer */
740 data_len = ares_dns_rr_remaining_len(buf, orig_len, rdlength);
741 if (data_len == 0) {
742 status = ARES_EBADRESP;
743 return status;
744 }
745 status = ares_buf_fetch_bytes_dup(buf, data_len, ARES_TRUE, &data);
746 if (status != ARES_SUCCESS) {
747 return status;
748 }
749
750 status = ares_dns_rr_set_bin_own(rr, ARES_RR_CAA_VALUE, data, data_len);
751 if (status != ARES_SUCCESS) {
752 ares_free(data);
753 return status;
754 }
755 data = NULL;
756
757 return ARES_SUCCESS;
758 }
759
ares_dns_parse_rr_raw_rr(ares_buf_t * buf,ares_dns_rr_t * rr,size_t rdlength,unsigned short raw_type)760 static ares_status_t ares_dns_parse_rr_raw_rr(ares_buf_t *buf,
761 ares_dns_rr_t *rr,
762 size_t rdlength,
763 unsigned short raw_type)
764 {
765 ares_status_t status;
766 unsigned char *bytes = NULL;
767
768 if (rdlength == 0) {
769 return ARES_SUCCESS;
770 }
771
772 status = ares_buf_fetch_bytes_dup(buf, rdlength, ARES_FALSE, &bytes);
773 if (status != ARES_SUCCESS) {
774 return status;
775 }
776
777 /* Can't fail */
778 status = ares_dns_rr_set_u16(rr, ARES_RR_RAW_RR_TYPE, raw_type);
779 if (status != ARES_SUCCESS) {
780 ares_free(bytes);
781 return status;
782 }
783
784 status = ares_dns_rr_set_bin_own(rr, ARES_RR_RAW_RR_DATA, bytes, rdlength);
785 if (status != ARES_SUCCESS) {
786 ares_free(bytes);
787 return status;
788 }
789
790 return ARES_SUCCESS;
791 }
792
ares_dns_parse_header(ares_buf_t * buf,unsigned int flags,ares_dns_record_t ** dnsrec,unsigned short * qdcount,unsigned short * ancount,unsigned short * nscount,unsigned short * arcount)793 static ares_status_t ares_dns_parse_header(ares_buf_t *buf, unsigned int flags,
794 ares_dns_record_t **dnsrec,
795 unsigned short *qdcount,
796 unsigned short *ancount,
797 unsigned short *nscount,
798 unsigned short *arcount)
799 {
800 ares_status_t status = ARES_EBADRESP;
801 unsigned short u16;
802 unsigned short id;
803 unsigned short dns_flags = 0;
804 ares_dns_opcode_t opcode;
805 unsigned short rcode;
806
807 (void)flags; /* currently unused */
808
809 if (buf == NULL || dnsrec == NULL || qdcount == NULL || ancount == NULL ||
810 nscount == NULL || arcount == NULL) {
811 return ARES_EFORMERR;
812 }
813
814 *dnsrec = NULL;
815
816 /*
817 * RFC 1035 4.1.1. Header section format.
818 * and Updated by RFC 2065 to add AD and CD bits.
819 * 1 1 1 1 1 1
820 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
821 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
822 * | ID |
823 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
824 * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE |
825 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
826 * | QDCOUNT |
827 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
828 * | ANCOUNT |
829 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
830 * | NSCOUNT |
831 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
832 * | ARCOUNT |
833 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
834 */
835
836 /* ID */
837 status = ares_buf_fetch_be16(buf, &id);
838 if (status != ARES_SUCCESS) {
839 goto fail;
840 }
841
842 /* Flags */
843 status = ares_buf_fetch_be16(buf, &u16);
844 if (status != ARES_SUCCESS) {
845 goto fail;
846 }
847
848 /* QR */
849 if (u16 & 0x8000) {
850 dns_flags |= ARES_FLAG_QR;
851 }
852
853 /* OPCODE */
854 opcode = (u16 >> 11) & 0xf;
855
856 /* AA */
857 if (u16 & 0x400) {
858 dns_flags |= ARES_FLAG_AA;
859 }
860
861 /* TC */
862 if (u16 & 0x200) {
863 dns_flags |= ARES_FLAG_TC;
864 }
865
866 /* RD */
867 if (u16 & 0x100) {
868 dns_flags |= ARES_FLAG_RD;
869 }
870
871 /* RA */
872 if (u16 & 0x80) {
873 dns_flags |= ARES_FLAG_RA;
874 }
875
876 /* Z -- unused */
877
878 /* AD */
879 if (u16 & 0x20) {
880 dns_flags |= ARES_FLAG_AD;
881 }
882
883 /* CD */
884 if (u16 & 0x10) {
885 dns_flags |= ARES_FLAG_CD;
886 }
887
888 /* RCODE */
889 rcode = u16 & 0xf;
890
891 /* QDCOUNT */
892 status = ares_buf_fetch_be16(buf, qdcount);
893 if (status != ARES_SUCCESS) {
894 goto fail;
895 }
896
897 /* ANCOUNT */
898 status = ares_buf_fetch_be16(buf, ancount);
899 if (status != ARES_SUCCESS) {
900 goto fail;
901 }
902
903 /* NSCOUNT */
904 status = ares_buf_fetch_be16(buf, nscount);
905 if (status != ARES_SUCCESS) {
906 goto fail;
907 }
908
909 /* ARCOUNT */
910 status = ares_buf_fetch_be16(buf, arcount);
911 if (status != ARES_SUCCESS) {
912 goto fail;
913 }
914
915 status = ares_dns_record_create(dnsrec, id, dns_flags, opcode,
916 ARES_RCODE_NOERROR /* Temporary */);
917 if (status != ARES_SUCCESS) {
918 goto fail;
919 }
920
921 (*dnsrec)->raw_rcode = rcode;
922
923 if (*ancount > 0) {
924 status =
925 ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ANSWER, *ancount);
926 if (status != ARES_SUCCESS) {
927 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
928 }
929 }
930
931 if (*nscount > 0) {
932 status =
933 ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_AUTHORITY, *nscount);
934 if (status != ARES_SUCCESS) {
935 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
936 }
937 }
938
939 if (*arcount > 0) {
940 status =
941 ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ADDITIONAL, *arcount);
942 if (status != ARES_SUCCESS) {
943 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
944 }
945 }
946
947 return ARES_SUCCESS;
948
949 fail:
950 ares_dns_record_destroy(*dnsrec);
951 *dnsrec = NULL;
952 *qdcount = 0;
953 *ancount = 0;
954 *nscount = 0;
955 *arcount = 0;
956
957 return status;
958 }
959
960 static ares_status_t
ares_dns_parse_rr_data(ares_buf_t * buf,size_t rdlength,ares_dns_rr_t * rr,ares_dns_rec_type_t type,unsigned short raw_type,unsigned short raw_class,unsigned int raw_ttl)961 ares_dns_parse_rr_data(ares_buf_t *buf, size_t rdlength, ares_dns_rr_t *rr,
962 ares_dns_rec_type_t type, unsigned short raw_type,
963 unsigned short raw_class, unsigned int raw_ttl)
964 {
965 switch (type) {
966 case ARES_REC_TYPE_A:
967 return ares_dns_parse_rr_a(buf, rr, rdlength);
968 case ARES_REC_TYPE_NS:
969 return ares_dns_parse_rr_ns(buf, rr, rdlength);
970 case ARES_REC_TYPE_CNAME:
971 return ares_dns_parse_rr_cname(buf, rr, rdlength);
972 case ARES_REC_TYPE_SOA:
973 return ares_dns_parse_rr_soa(buf, rr, rdlength);
974 case ARES_REC_TYPE_PTR:
975 return ares_dns_parse_rr_ptr(buf, rr, rdlength);
976 case ARES_REC_TYPE_HINFO:
977 return ares_dns_parse_rr_hinfo(buf, rr, rdlength);
978 case ARES_REC_TYPE_MX:
979 return ares_dns_parse_rr_mx(buf, rr, rdlength);
980 case ARES_REC_TYPE_TXT:
981 return ares_dns_parse_rr_txt(buf, rr, rdlength);
982 case ARES_REC_TYPE_SIG:
983 return ares_dns_parse_rr_sig(buf, rr, rdlength);
984 case ARES_REC_TYPE_AAAA:
985 return ares_dns_parse_rr_aaaa(buf, rr, rdlength);
986 case ARES_REC_TYPE_SRV:
987 return ares_dns_parse_rr_srv(buf, rr, rdlength);
988 case ARES_REC_TYPE_NAPTR:
989 return ares_dns_parse_rr_naptr(buf, rr, rdlength);
990 case ARES_REC_TYPE_ANY:
991 return ARES_EBADRESP;
992 case ARES_REC_TYPE_OPT:
993 return ares_dns_parse_rr_opt(buf, rr, rdlength, raw_class, raw_ttl);
994 case ARES_REC_TYPE_TLSA:
995 return ares_dns_parse_rr_tlsa(buf, rr, rdlength);
996 case ARES_REC_TYPE_SVCB:
997 return ares_dns_parse_rr_svcb(buf, rr, rdlength);
998 case ARES_REC_TYPE_HTTPS:
999 return ares_dns_parse_rr_https(buf, rr, rdlength);
1000 case ARES_REC_TYPE_URI:
1001 return ares_dns_parse_rr_uri(buf, rr, rdlength);
1002 case ARES_REC_TYPE_CAA:
1003 return ares_dns_parse_rr_caa(buf, rr, rdlength);
1004 case ARES_REC_TYPE_RAW_RR:
1005 return ares_dns_parse_rr_raw_rr(buf, rr, rdlength, raw_type);
1006 }
1007 return ARES_EFORMERR;
1008 }
1009
ares_dns_parse_qd(ares_buf_t * buf,ares_dns_record_t * dnsrec)1010 static ares_status_t ares_dns_parse_qd(ares_buf_t *buf,
1011 ares_dns_record_t *dnsrec)
1012 {
1013 char *name = NULL;
1014 unsigned short u16;
1015 ares_status_t status;
1016 ares_dns_rec_type_t type;
1017 ares_dns_class_t qclass;
1018 /* The question section is used to carry the "question" in most queries,
1019 * i.e., the parameters that define what is being asked. The section
1020 * contains QDCOUNT (usually 1) entries, each of the following format:
1021 * 1 1 1 1 1 1
1022 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
1023 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1024 * | |
1025 * / QNAME /
1026 * / /
1027 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1028 * | QTYPE |
1029 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1030 * | QCLASS |
1031 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1032 */
1033
1034 /* Name */
1035 status = ares_dns_name_parse(buf, &name, ARES_FALSE);
1036 if (status != ARES_SUCCESS) {
1037 goto done;
1038 }
1039
1040 /* Type */
1041 status = ares_buf_fetch_be16(buf, &u16);
1042 if (status != ARES_SUCCESS) {
1043 goto done;
1044 }
1045 type = u16;
1046
1047 /* Class */
1048 status = ares_buf_fetch_be16(buf, &u16);
1049 if (status != ARES_SUCCESS) {
1050 goto done;
1051 }
1052 qclass = u16;
1053
1054 /* Add question */
1055 status = ares_dns_record_query_add(dnsrec, name, type, qclass);
1056 if (status != ARES_SUCCESS) {
1057 goto done;
1058 }
1059
1060 done:
1061 ares_free(name);
1062 return status;
1063 }
1064
ares_dns_parse_rr(ares_buf_t * buf,unsigned int flags,ares_dns_section_t sect,ares_dns_record_t * dnsrec)1065 static ares_status_t ares_dns_parse_rr(ares_buf_t *buf, unsigned int flags,
1066 ares_dns_section_t sect,
1067 ares_dns_record_t *dnsrec)
1068 {
1069 char *name = NULL;
1070 unsigned short u16;
1071 unsigned short raw_type;
1072 ares_status_t status;
1073 ares_dns_rec_type_t type;
1074 ares_dns_class_t qclass;
1075 unsigned int ttl;
1076 size_t rdlength;
1077 ares_dns_rr_t *rr = NULL;
1078 size_t remaining_len = 0;
1079 size_t processed_len = 0;
1080 ares_bool_t namecomp;
1081
1082 /* All RRs have the same top level format shown below:
1083 * 1 1 1 1 1 1
1084 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
1085 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1086 * | |
1087 * / /
1088 * / NAME /
1089 * | |
1090 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1091 * | TYPE |
1092 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1093 * | CLASS |
1094 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1095 * | TTL |
1096 * | |
1097 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1098 * | RDLENGTH |
1099 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
1100 * / RDATA /
1101 * / /
1102 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1103 */
1104
1105 /* Name */
1106 status = ares_dns_name_parse(buf, &name, ARES_FALSE);
1107 if (status != ARES_SUCCESS) {
1108 goto done;
1109 }
1110
1111 /* Type */
1112 status = ares_buf_fetch_be16(buf, &u16);
1113 if (status != ARES_SUCCESS) {
1114 goto done;
1115 }
1116 type = u16;
1117 raw_type = u16; /* Only used for raw rr data */
1118
1119 /* Class */
1120 status = ares_buf_fetch_be16(buf, &u16);
1121 if (status != ARES_SUCCESS) {
1122 goto done;
1123 }
1124 qclass = u16;
1125
1126 /* TTL */
1127 status = ares_buf_fetch_be32(buf, &ttl);
1128 if (status != ARES_SUCCESS) {
1129 goto done;
1130 }
1131
1132 /* Length */
1133 status = ares_buf_fetch_be16(buf, &u16);
1134 if (status != ARES_SUCCESS) {
1135 goto done;
1136 }
1137 rdlength = u16;
1138
1139 if (!ares_dns_rec_type_isvalid(type, ARES_FALSE)) {
1140 type = ARES_REC_TYPE_RAW_RR;
1141 }
1142
1143 namecomp = ares_dns_rec_allow_name_comp(type);
1144 if (sect == ARES_SECTION_ANSWER &&
1145 (flags &
1146 (namecomp ? ARES_DNS_PARSE_AN_BASE_RAW : ARES_DNS_PARSE_AN_EXT_RAW))) {
1147 type = ARES_REC_TYPE_RAW_RR;
1148 }
1149 if (sect == ARES_SECTION_AUTHORITY &&
1150 (flags &
1151 (namecomp ? ARES_DNS_PARSE_NS_BASE_RAW : ARES_DNS_PARSE_NS_EXT_RAW))) {
1152 type = ARES_REC_TYPE_RAW_RR;
1153 }
1154 if (sect == ARES_SECTION_ADDITIONAL &&
1155 (flags &
1156 (namecomp ? ARES_DNS_PARSE_AR_BASE_RAW : ARES_DNS_PARSE_AR_EXT_RAW))) {
1157 type = ARES_REC_TYPE_RAW_RR;
1158 }
1159
1160 /* Pull into another buffer for safety */
1161 if (rdlength > ares_buf_len(buf)) {
1162 status = ARES_EBADRESP;
1163 goto done;
1164 }
1165
1166 /* Add the base rr */
1167 status =
1168 ares_dns_record_rr_add(&rr, dnsrec, sect, name, type,
1169 type == ARES_REC_TYPE_OPT ? ARES_CLASS_IN : qclass,
1170 type == ARES_REC_TYPE_OPT ? 0 : ttl);
1171 if (status != ARES_SUCCESS) {
1172 goto done;
1173 }
1174
1175 /* Record the current remaining length in the buffer so we can tell how
1176 * much was processed */
1177 remaining_len = ares_buf_len(buf);
1178
1179 /* Fill in the data for the rr */
1180 status = ares_dns_parse_rr_data(buf, rdlength, rr, type, raw_type,
1181 (unsigned short)qclass, ttl);
1182 if (status != ARES_SUCCESS) {
1183 goto done;
1184 }
1185
1186 /* Determine how many bytes were processed */
1187 processed_len = remaining_len - ares_buf_len(buf);
1188
1189 /* If too many bytes were processed, error! */
1190 if (processed_len > rdlength) {
1191 status = ARES_EBADRESP;
1192 goto done;
1193 }
1194
1195 /* If too few bytes were processed, consume the unprocessed data for this
1196 * record as the parser may not have wanted/needed to use it */
1197 if (processed_len < rdlength) {
1198 ares_buf_consume(buf, rdlength - processed_len);
1199 }
1200
1201
1202 done:
1203 ares_free(name);
1204 return status;
1205 }
1206
ares_dns_parse_buf(ares_buf_t * buf,unsigned int flags,ares_dns_record_t ** dnsrec)1207 static ares_status_t ares_dns_parse_buf(ares_buf_t *buf, unsigned int flags,
1208 ares_dns_record_t **dnsrec)
1209 {
1210 ares_status_t status;
1211 unsigned short qdcount;
1212 unsigned short ancount;
1213 unsigned short nscount;
1214 unsigned short arcount;
1215 unsigned short i;
1216
1217 if (buf == NULL || dnsrec == NULL) {
1218 return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
1219 }
1220
1221 /* Maximum DNS packet size is 64k, even over TCP */
1222 if (ares_buf_len(buf) > 0xFFFF) {
1223 return ARES_EFORMERR;
1224 }
1225
1226 /* All communications inside of the domain protocol are carried in a single
1227 * format called a message. The top level format of message is divided
1228 * into 5 sections (some of which are empty in certain cases) shown below:
1229 *
1230 * +---------------------+
1231 * | Header |
1232 * +---------------------+
1233 * | Question | the question for the name server
1234 * +---------------------+
1235 * | Answer | RRs answering the question
1236 * +---------------------+
1237 * | Authority | RRs pointing toward an authority
1238 * +---------------------+
1239 * | Additional | RRs holding additional information
1240 * +---------------------+
1241 */
1242
1243 /* Parse header */
1244 status = ares_dns_parse_header(buf, flags, dnsrec, &qdcount, &ancount,
1245 &nscount, &arcount);
1246 if (status != ARES_SUCCESS) {
1247 goto fail;
1248 }
1249
1250 /* Must have questions */
1251 if (qdcount == 0) {
1252 status = ARES_EBADRESP;
1253 goto fail;
1254 }
1255
1256 /* XXX: this should be controlled by a flag in case we want to allow
1257 * multiple questions. I think mDNS allows this */
1258 if (qdcount > 1) {
1259 status = ARES_EBADRESP;
1260 goto fail;
1261 }
1262
1263 /* Parse questions */
1264 for (i = 0; i < qdcount; i++) {
1265 status = ares_dns_parse_qd(buf, *dnsrec);
1266 if (status != ARES_SUCCESS) {
1267 goto fail;
1268 }
1269 }
1270
1271 /* Parse Answers */
1272 for (i = 0; i < ancount; i++) {
1273 status = ares_dns_parse_rr(buf, flags, ARES_SECTION_ANSWER, *dnsrec);
1274 if (status != ARES_SUCCESS) {
1275 goto fail;
1276 }
1277 }
1278
1279 /* Parse Authority */
1280 for (i = 0; i < nscount; i++) {
1281 status = ares_dns_parse_rr(buf, flags, ARES_SECTION_AUTHORITY, *dnsrec);
1282 if (status != ARES_SUCCESS) {
1283 goto fail;
1284 }
1285 }
1286
1287 /* Parse Additional */
1288 for (i = 0; i < arcount; i++) {
1289 status = ares_dns_parse_rr(buf, flags, ARES_SECTION_ADDITIONAL, *dnsrec);
1290 if (status != ARES_SUCCESS) {
1291 goto fail;
1292 }
1293 }
1294
1295 /* Finalize rcode now that if we have OPT it is processed */
1296 if (!ares_dns_rcode_isvalid((*dnsrec)->raw_rcode)) {
1297 (*dnsrec)->rcode = ARES_RCODE_SERVFAIL;
1298 } else {
1299 (*dnsrec)->rcode = (ares_dns_rcode_t)(*dnsrec)->raw_rcode;
1300 }
1301
1302 return ARES_SUCCESS;
1303
1304 fail:
1305 ares_dns_record_destroy(*dnsrec);
1306 *dnsrec = NULL;
1307 return status;
1308 }
1309
ares_dns_parse(const unsigned char * buf,size_t buf_len,unsigned int flags,ares_dns_record_t ** dnsrec)1310 ares_status_t ares_dns_parse(const unsigned char *buf, size_t buf_len,
1311 unsigned int flags, ares_dns_record_t **dnsrec)
1312 {
1313 ares_buf_t *parser = NULL;
1314 ares_status_t status;
1315
1316 if (buf == NULL || buf_len == 0 || dnsrec == NULL) {
1317 return ARES_EFORMERR;
1318 }
1319
1320 parser = ares_buf_create_const(buf, buf_len);
1321 if (parser == NULL) {
1322 return ARES_ENOMEM;
1323 }
1324
1325 status = ares_dns_parse_buf(parser, flags, dnsrec);
1326 ares_buf_destroy(parser);
1327
1328 return status;
1329 }
1330