• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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