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