• 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_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 
34 
ares_dns_record_create(ares_dns_record_t ** dnsrec,unsigned short id,unsigned short flags,ares_dns_opcode_t opcode,ares_dns_rcode_t rcode)35 ares_status_t ares_dns_record_create(ares_dns_record_t **dnsrec,
36                                      unsigned short id, unsigned short flags,
37                                      ares_dns_opcode_t opcode,
38                                      ares_dns_rcode_t  rcode)
39 {
40   if (dnsrec == NULL) {
41     return ARES_EFORMERR;
42   }
43 
44   *dnsrec = NULL;
45 
46   if (!ares_dns_opcode_isvalid(opcode) || !ares_dns_rcode_isvalid(rcode) ||
47       !ares_dns_flags_arevalid(flags)) {
48     return ARES_EFORMERR;
49   }
50 
51   *dnsrec = ares_malloc_zero(sizeof(**dnsrec));
52   if (*dnsrec == NULL) {
53     return ARES_ENOMEM;
54   }
55 
56   (*dnsrec)->id     = id;
57   (*dnsrec)->flags  = flags;
58   (*dnsrec)->opcode = opcode;
59   (*dnsrec)->rcode  = rcode;
60   return ARES_SUCCESS;
61 }
62 
ares_dns_record_get_id(const ares_dns_record_t * dnsrec)63 unsigned short ares_dns_record_get_id(const ares_dns_record_t *dnsrec)
64 {
65   if (dnsrec == NULL) {
66     return 0;
67   }
68   return dnsrec->id;
69 }
70 
ares_dns_record_get_flags(const ares_dns_record_t * dnsrec)71 unsigned short ares_dns_record_get_flags(const ares_dns_record_t *dnsrec)
72 {
73   if (dnsrec == NULL) {
74     return 0;
75   }
76   return dnsrec->flags;
77 }
78 
ares_dns_record_get_opcode(const ares_dns_record_t * dnsrec)79 ares_dns_opcode_t ares_dns_record_get_opcode(const ares_dns_record_t *dnsrec)
80 {
81   if (dnsrec == NULL) {
82     return 0;
83   }
84   return dnsrec->opcode;
85 }
86 
ares_dns_record_get_rcode(const ares_dns_record_t * dnsrec)87 ares_dns_rcode_t ares_dns_record_get_rcode(const ares_dns_record_t *dnsrec)
88 {
89   if (dnsrec == NULL) {
90     return 0;
91   }
92   return dnsrec->rcode;
93 }
94 
ares__dns_options_free(ares__dns_options_t * options)95 static void ares__dns_options_free(ares__dns_options_t *options)
96 {
97   size_t i;
98 
99   if (options == NULL) {
100     return;
101   }
102 
103   for (i = 0; i < options->cnt; i++) {
104     ares_free(options->optval[i].val);
105   }
106   ares_free(options->optval);
107   ares_free(options);
108 }
109 
ares__dns_rr_free(ares_dns_rr_t * rr)110 static void ares__dns_rr_free(ares_dns_rr_t *rr)
111 {
112   ares_free(rr->name);
113 
114   switch (rr->type) {
115     case ARES_REC_TYPE_A:
116     case ARES_REC_TYPE_AAAA:
117     case ARES_REC_TYPE_ANY:
118       /* Nothing to free */
119       break;
120 
121     case ARES_REC_TYPE_NS:
122       ares_free(rr->r.ns.nsdname);
123       break;
124 
125     case ARES_REC_TYPE_CNAME:
126       ares_free(rr->r.cname.cname);
127       break;
128 
129     case ARES_REC_TYPE_SOA:
130       ares_free(rr->r.soa.mname);
131       ares_free(rr->r.soa.rname);
132       break;
133 
134     case ARES_REC_TYPE_PTR:
135       ares_free(rr->r.ptr.dname);
136       break;
137 
138     case ARES_REC_TYPE_HINFO:
139       ares_free(rr->r.hinfo.cpu);
140       ares_free(rr->r.hinfo.os);
141       break;
142 
143     case ARES_REC_TYPE_MX:
144       ares_free(rr->r.mx.exchange);
145       break;
146 
147     case ARES_REC_TYPE_TXT:
148       ares_free(rr->r.txt.data);
149       break;
150 
151     case ARES_REC_TYPE_SRV:
152       ares_free(rr->r.srv.target);
153       break;
154 
155     case ARES_REC_TYPE_NAPTR:
156       ares_free(rr->r.naptr.flags);
157       ares_free(rr->r.naptr.services);
158       ares_free(rr->r.naptr.regexp);
159       ares_free(rr->r.naptr.replacement);
160       break;
161 
162     case ARES_REC_TYPE_OPT:
163       ares__dns_options_free(rr->r.opt.options);
164       break;
165 
166     case ARES_REC_TYPE_TLSA:
167       ares_free(rr->r.tlsa.data);
168       break;
169 
170     case ARES_REC_TYPE_SVCB:
171       ares_free(rr->r.svcb.target);
172       ares__dns_options_free(rr->r.svcb.params);
173       break;
174 
175     case ARES_REC_TYPE_HTTPS:
176       ares_free(rr->r.https.target);
177       ares__dns_options_free(rr->r.https.params);
178       break;
179 
180     case ARES_REC_TYPE_URI:
181       ares_free(rr->r.uri.target);
182       break;
183 
184     case ARES_REC_TYPE_CAA:
185       ares_free(rr->r.caa.tag);
186       ares_free(rr->r.caa.value);
187       break;
188 
189     case ARES_REC_TYPE_RAW_RR:
190       ares_free(rr->r.raw_rr.data);
191       break;
192   }
193 }
194 
ares_dns_record_destroy(ares_dns_record_t * dnsrec)195 void ares_dns_record_destroy(ares_dns_record_t *dnsrec)
196 {
197   size_t i;
198 
199   if (dnsrec == NULL) {
200     return;
201   }
202 
203   /* Free questions */
204   for (i = 0; i < dnsrec->qdcount; i++) {
205     ares_free(dnsrec->qd[i].name);
206   }
207   ares_free(dnsrec->qd);
208 
209   /* Free answers */
210   for (i = 0; i < dnsrec->ancount; i++) {
211     ares__dns_rr_free(&dnsrec->an[i]);
212   }
213   ares_free(dnsrec->an);
214 
215   /* Free authority */
216   for (i = 0; i < dnsrec->nscount; i++) {
217     ares__dns_rr_free(&dnsrec->ns[i]);
218   }
219   ares_free(dnsrec->ns);
220 
221   /* Free additional */
222   for (i = 0; i < dnsrec->arcount; i++) {
223     ares__dns_rr_free(&dnsrec->ar[i]);
224   }
225   ares_free(dnsrec->ar);
226 
227   ares_free(dnsrec);
228 }
229 
ares_dns_record_query_cnt(const ares_dns_record_t * dnsrec)230 size_t ares_dns_record_query_cnt(const ares_dns_record_t *dnsrec)
231 {
232   if (dnsrec == NULL) {
233     return 0;
234   }
235   return dnsrec->qdcount;
236 }
237 
ares_dns_record_query_add(ares_dns_record_t * dnsrec,const char * name,ares_dns_rec_type_t qtype,ares_dns_class_t qclass)238 ares_status_t ares_dns_record_query_add(ares_dns_record_t  *dnsrec,
239                                         const char         *name,
240                                         ares_dns_rec_type_t qtype,
241                                         ares_dns_class_t    qclass)
242 {
243   ares_dns_qd_t *temp = NULL;
244   size_t         idx;
245 
246   if (dnsrec == NULL || name == NULL ||
247       !ares_dns_rec_type_isvalid(qtype, ARES_TRUE) ||
248       !ares_dns_class_isvalid(qclass, ARES_TRUE)) {
249     return ARES_EFORMERR;
250   }
251 
252   if (dnsrec->qdcount >= dnsrec->qdalloc) {
253     size_t alloc_cnt = ares__round_up_pow2(dnsrec->qdcount + 1);
254 
255     temp = ares_realloc_zero(dnsrec->qd, sizeof(*temp) * (dnsrec->qdalloc),
256                              sizeof(*temp) * alloc_cnt);
257     if (temp == NULL) {
258       return ARES_ENOMEM;
259     }
260 
261     dnsrec->qdalloc = alloc_cnt;
262     dnsrec->qd      = temp;
263   }
264 
265   idx = dnsrec->qdcount;
266 
267   dnsrec->qd[idx].name = ares_strdup(name);
268   if (dnsrec->qd[idx].name == NULL) {
269     /* No need to clean up anything */
270     return ARES_ENOMEM;
271   }
272 
273   dnsrec->qd[idx].qtype  = qtype;
274   dnsrec->qd[idx].qclass = qclass;
275   dnsrec->qdcount++;
276   return ARES_SUCCESS;
277 }
278 
ares_dns_record_query_get(const ares_dns_record_t * dnsrec,size_t idx,const char ** name,ares_dns_rec_type_t * qtype,ares_dns_class_t * qclass)279 ares_status_t ares_dns_record_query_get(const ares_dns_record_t *dnsrec,
280                                         size_t idx, const char **name,
281                                         ares_dns_rec_type_t *qtype,
282                                         ares_dns_class_t    *qclass)
283 {
284   if (dnsrec == NULL || idx >= dnsrec->qdcount) {
285     return ARES_EFORMERR;
286   }
287 
288   if (name != NULL) {
289     *name = dnsrec->qd[idx].name;
290   }
291 
292   if (qtype != NULL) {
293     *qtype = dnsrec->qd[idx].qtype;
294   }
295 
296   if (qclass != NULL) {
297     *qclass = dnsrec->qd[idx].qclass;
298   }
299 
300   return ARES_SUCCESS;
301 }
302 
ares_dns_record_rr_cnt(const ares_dns_record_t * dnsrec,ares_dns_section_t sect)303 size_t ares_dns_record_rr_cnt(const ares_dns_record_t *dnsrec,
304                               ares_dns_section_t       sect)
305 {
306   if (dnsrec == NULL || !ares_dns_section_isvalid(sect)) {
307     return 0;
308   }
309 
310   switch (sect) {
311     case ARES_SECTION_ANSWER:
312       return dnsrec->ancount;
313     case ARES_SECTION_AUTHORITY:
314       return dnsrec->nscount;
315     case ARES_SECTION_ADDITIONAL:
316       return dnsrec->arcount;
317   }
318 
319   return 0;
320 }
321 
ares_dns_record_rr_prealloc(ares_dns_record_t * dnsrec,ares_dns_section_t sect,size_t cnt)322 ares_status_t ares_dns_record_rr_prealloc(ares_dns_record_t *dnsrec,
323                                           ares_dns_section_t sect, size_t cnt)
324 {
325   ares_dns_rr_t **rr_ptr   = NULL;
326   size_t         *rr_alloc = NULL;
327   ares_dns_rr_t  *temp     = NULL;
328 
329   if (dnsrec == NULL || cnt == 0 || !ares_dns_section_isvalid(sect)) {
330     return ARES_EFORMERR;
331   }
332 
333   switch (sect) {
334     case ARES_SECTION_ANSWER:
335       rr_ptr   = &dnsrec->an;
336       rr_alloc = &dnsrec->analloc;
337       break;
338     case ARES_SECTION_AUTHORITY:
339       rr_ptr   = &dnsrec->ns;
340       rr_alloc = &dnsrec->nsalloc;
341       break;
342     case ARES_SECTION_ADDITIONAL:
343       rr_ptr   = &dnsrec->ar;
344       rr_alloc = &dnsrec->aralloc;
345       break;
346   }
347 
348   /* Round up cnt to a power of 2 */
349   cnt = ares__round_up_pow2(cnt);
350 
351   /* Already have that */
352   if (cnt <= *rr_alloc) {
353     return ARES_SUCCESS;
354   }
355 
356   temp = ares_realloc_zero(*rr_ptr, sizeof(*temp) * (*rr_alloc),
357                            sizeof(*temp) * cnt);
358   if (temp == NULL) {
359     return ARES_ENOMEM;
360   }
361 
362   *rr_alloc = cnt;
363   *rr_ptr   = temp;
364   return ARES_SUCCESS;
365 }
366 
ares_dns_record_rr_add(ares_dns_rr_t ** rr_out,ares_dns_record_t * dnsrec,ares_dns_section_t sect,const char * name,ares_dns_rec_type_t type,ares_dns_class_t rclass,unsigned int ttl)367 ares_status_t ares_dns_record_rr_add(ares_dns_rr_t    **rr_out,
368                                      ares_dns_record_t *dnsrec,
369                                      ares_dns_section_t sect, const char *name,
370                                      ares_dns_rec_type_t type,
371                                      ares_dns_class_t rclass, unsigned int ttl)
372 {
373   ares_dns_rr_t **rr_ptr = NULL;
374   ares_dns_rr_t  *rr     = NULL;
375   size_t         *rr_len = NULL;
376   ares_status_t   status;
377   size_t          idx;
378 
379   if (dnsrec == NULL || name == NULL || rr_out == NULL ||
380       !ares_dns_section_isvalid(sect) ||
381       !ares_dns_rec_type_isvalid(type, ARES_FALSE) ||
382       !ares_dns_class_isvalid(rclass, ARES_FALSE)) {
383     return ARES_EFORMERR;
384   }
385 
386   *rr_out = NULL;
387 
388   switch (sect) {
389     case ARES_SECTION_ANSWER:
390       rr_ptr = &dnsrec->an;
391       rr_len = &dnsrec->ancount;
392       break;
393     case ARES_SECTION_AUTHORITY:
394       rr_ptr = &dnsrec->ns;
395       rr_len = &dnsrec->nscount;
396       break;
397     case ARES_SECTION_ADDITIONAL:
398       rr_ptr = &dnsrec->ar;
399       rr_len = &dnsrec->arcount;
400       break;
401   }
402 
403   status = ares_dns_record_rr_prealloc(dnsrec, sect, *rr_len + 1);
404   if (status != ARES_SUCCESS) {
405     return status;
406   }
407 
408   idx = *rr_len;
409   rr  = &(*rr_ptr)[idx];
410 
411   rr->name = ares_strdup(name);
412   if (rr->name == NULL) {
413     /* No need to clean up anything */
414     return ARES_ENOMEM;
415   }
416 
417   rr->parent = dnsrec;
418   rr->type   = type;
419   rr->rclass = rclass;
420   rr->ttl    = ttl;
421   (*rr_len)++;
422 
423   *rr_out = rr;
424 
425   return ARES_SUCCESS;
426 }
427 
ares_dns_record_rr_del(ares_dns_record_t * dnsrec,ares_dns_section_t sect,size_t idx)428 ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec,
429                                      ares_dns_section_t sect, size_t idx)
430 {
431   ares_dns_rr_t *rr_ptr = NULL;
432   size_t        *rr_len = NULL;
433   size_t         cnt_after;
434 
435   if (dnsrec == NULL || !ares_dns_section_isvalid(sect)) {
436     return ARES_EFORMERR;
437   }
438 
439   switch (sect) {
440     case ARES_SECTION_ANSWER:
441       rr_ptr = dnsrec->an;
442       rr_len = &dnsrec->ancount;
443       break;
444     case ARES_SECTION_AUTHORITY:
445       rr_ptr = dnsrec->ns;
446       rr_len = &dnsrec->nscount;
447       break;
448     case ARES_SECTION_ADDITIONAL:
449       rr_ptr = dnsrec->ar;
450       rr_len = &dnsrec->arcount;
451       break;
452   }
453 
454   if (idx >= *rr_len) {
455     return ARES_EFORMERR;
456   }
457 
458   ares__dns_rr_free(&rr_ptr[idx]);
459 
460   cnt_after = *rr_len - idx - 1;
461 
462   if (cnt_after) {
463     memmove(&rr_ptr[idx], &rr_ptr[idx + 1], sizeof(*rr_ptr) * cnt_after);
464   }
465 
466   (*rr_len)--;
467   return ARES_SUCCESS;
468 }
469 
ares_dns_record_rr_get(ares_dns_record_t * dnsrec,ares_dns_section_t sect,size_t idx)470 ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec,
471                                       ares_dns_section_t sect, size_t idx)
472 {
473   ares_dns_rr_t *rr_ptr = NULL;
474   size_t         rr_len = 0;
475 
476   if (dnsrec == NULL || !ares_dns_section_isvalid(sect)) {
477     return NULL;
478   }
479 
480   switch (sect) {
481     case ARES_SECTION_ANSWER:
482       rr_ptr = dnsrec->an;
483       rr_len = dnsrec->ancount;
484       break;
485     case ARES_SECTION_AUTHORITY:
486       rr_ptr = dnsrec->ns;
487       rr_len = dnsrec->nscount;
488       break;
489     case ARES_SECTION_ADDITIONAL:
490       rr_ptr = dnsrec->ar;
491       rr_len = dnsrec->arcount;
492       break;
493   }
494 
495   if (idx >= rr_len) {
496     return NULL;
497   }
498 
499   return &rr_ptr[idx];
500 }
501 
502 static const ares_dns_rr_t *
ares_dns_record_rr_get_const(const ares_dns_record_t * dnsrec,ares_dns_section_t sect,size_t idx)503   ares_dns_record_rr_get_const(const ares_dns_record_t *dnsrec,
504                                ares_dns_section_t sect, size_t idx)
505 {
506   return ares_dns_record_rr_get((void *)((size_t)dnsrec), sect, idx);
507 }
508 
ares_dns_rr_get_name(const ares_dns_rr_t * rr)509 const char *ares_dns_rr_get_name(const ares_dns_rr_t *rr)
510 {
511   if (rr == NULL) {
512     return NULL;
513   }
514   return rr->name;
515 }
516 
ares_dns_rr_get_type(const ares_dns_rr_t * rr)517 ares_dns_rec_type_t ares_dns_rr_get_type(const ares_dns_rr_t *rr)
518 {
519   if (rr == NULL) {
520     return 0;
521   }
522   return rr->type;
523 }
524 
ares_dns_rr_get_class(const ares_dns_rr_t * rr)525 ares_dns_class_t ares_dns_rr_get_class(const ares_dns_rr_t *rr)
526 {
527   if (rr == NULL) {
528     return 0;
529   }
530   return rr->rclass;
531 }
532 
ares_dns_rr_get_ttl(const ares_dns_rr_t * rr)533 unsigned int ares_dns_rr_get_ttl(const ares_dns_rr_t *rr)
534 {
535   if (rr == NULL) {
536     return 0;
537   }
538   return rr->ttl;
539 }
540 
ares_dns_rr_data_ptr(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,size_t ** lenptr)541 static void *ares_dns_rr_data_ptr(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
542                                   size_t **lenptr)
543 {
544   if (dns_rr == NULL || dns_rr->type != ares_dns_rr_key_to_rec_type(key)) {
545     return NULL;
546   }
547 
548   switch (key) {
549     case ARES_RR_A_ADDR:
550       return &dns_rr->r.a.addr;
551 
552     case ARES_RR_NS_NSDNAME:
553       return &dns_rr->r.ns.nsdname;
554 
555     case ARES_RR_CNAME_CNAME:
556       return &dns_rr->r.cname.cname;
557 
558     case ARES_RR_SOA_MNAME:
559       return &dns_rr->r.soa.mname;
560 
561     case ARES_RR_SOA_RNAME:
562       return &dns_rr->r.soa.rname;
563 
564     case ARES_RR_SOA_SERIAL:
565       return &dns_rr->r.soa.serial;
566 
567     case ARES_RR_SOA_REFRESH:
568       return &dns_rr->r.soa.refresh;
569 
570     case ARES_RR_SOA_RETRY:
571       return &dns_rr->r.soa.retry;
572 
573     case ARES_RR_SOA_EXPIRE:
574       return &dns_rr->r.soa.expire;
575 
576     case ARES_RR_SOA_MINIMUM:
577       return &dns_rr->r.soa.minimum;
578 
579     case ARES_RR_PTR_DNAME:
580       return &dns_rr->r.ptr.dname;
581 
582     case ARES_RR_AAAA_ADDR:
583       return &dns_rr->r.aaaa.addr;
584 
585     case ARES_RR_HINFO_CPU:
586       return &dns_rr->r.hinfo.cpu;
587 
588     case ARES_RR_HINFO_OS:
589       return &dns_rr->r.hinfo.os;
590 
591     case ARES_RR_MX_PREFERENCE:
592       return &dns_rr->r.mx.preference;
593 
594     case ARES_RR_MX_EXCHANGE:
595       return &dns_rr->r.mx.exchange;
596 
597     case ARES_RR_TXT_DATA:
598       if (lenptr == NULL) {
599         return NULL;
600       }
601       *lenptr = &dns_rr->r.txt.data_len;
602       return &dns_rr->r.txt.data;
603 
604     case ARES_RR_SRV_PRIORITY:
605       return &dns_rr->r.srv.priority;
606 
607     case ARES_RR_SRV_WEIGHT:
608       return &dns_rr->r.srv.weight;
609 
610     case ARES_RR_SRV_PORT:
611       return &dns_rr->r.srv.port;
612 
613     case ARES_RR_SRV_TARGET:
614       return &dns_rr->r.srv.target;
615 
616     case ARES_RR_NAPTR_ORDER:
617       return &dns_rr->r.naptr.order;
618 
619     case ARES_RR_NAPTR_PREFERENCE:
620       return &dns_rr->r.naptr.preference;
621 
622     case ARES_RR_NAPTR_FLAGS:
623       return &dns_rr->r.naptr.flags;
624 
625     case ARES_RR_NAPTR_SERVICES:
626       return &dns_rr->r.naptr.services;
627 
628     case ARES_RR_NAPTR_REGEXP:
629       return &dns_rr->r.naptr.regexp;
630 
631     case ARES_RR_NAPTR_REPLACEMENT:
632       return &dns_rr->r.naptr.replacement;
633 
634     case ARES_RR_OPT_UDP_SIZE:
635       return &dns_rr->r.opt.udp_size;
636 
637     case ARES_RR_OPT_VERSION:
638       return &dns_rr->r.opt.version;
639 
640     case ARES_RR_OPT_FLAGS:
641       return &dns_rr->r.opt.flags;
642 
643     case ARES_RR_OPT_OPTIONS:
644       return &dns_rr->r.opt.options;
645 
646     case ARES_RR_TLSA_CERT_USAGE:
647       return &dns_rr->r.tlsa.cert_usage;
648 
649     case ARES_RR_TLSA_SELECTOR:
650       return &dns_rr->r.tlsa.selector;
651 
652     case ARES_RR_TLSA_MATCH:
653       return &dns_rr->r.tlsa.match;
654 
655     case ARES_RR_TLSA_DATA:
656       if (lenptr == NULL) {
657         return NULL;
658       }
659       *lenptr = &dns_rr->r.tlsa.data_len;
660       return &dns_rr->r.tlsa.data;
661 
662     case ARES_RR_SVCB_PRIORITY:
663       return &dns_rr->r.svcb.priority;
664 
665     case ARES_RR_SVCB_TARGET:
666       return &dns_rr->r.svcb.target;
667 
668     case ARES_RR_SVCB_PARAMS:
669       return &dns_rr->r.svcb.params;
670 
671     case ARES_RR_HTTPS_PRIORITY:
672       return &dns_rr->r.https.priority;
673 
674     case ARES_RR_HTTPS_TARGET:
675       return &dns_rr->r.https.target;
676 
677     case ARES_RR_HTTPS_PARAMS:
678       return &dns_rr->r.https.params;
679 
680     case ARES_RR_URI_PRIORITY:
681       return &dns_rr->r.uri.priority;
682 
683     case ARES_RR_URI_WEIGHT:
684       return &dns_rr->r.uri.weight;
685 
686     case ARES_RR_URI_TARGET:
687       return &dns_rr->r.uri.target;
688 
689     case ARES_RR_CAA_CRITICAL:
690       return &dns_rr->r.caa.critical;
691 
692     case ARES_RR_CAA_TAG:
693       return &dns_rr->r.caa.tag;
694 
695     case ARES_RR_CAA_VALUE:
696       if (lenptr == NULL) {
697         return NULL;
698       }
699       *lenptr = &dns_rr->r.caa.value_len;
700       return &dns_rr->r.caa.value;
701 
702     case ARES_RR_RAW_RR_TYPE:
703       return &dns_rr->r.raw_rr.type;
704 
705     case ARES_RR_RAW_RR_DATA:
706       if (lenptr == NULL) {
707         return NULL;
708       }
709       *lenptr = &dns_rr->r.raw_rr.length;
710       return &dns_rr->r.raw_rr.data;
711   }
712 
713   return NULL;
714 }
715 
ares_dns_rr_data_ptr_const(const ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,const size_t ** lenptr)716 static const void *ares_dns_rr_data_ptr_const(const ares_dns_rr_t *dns_rr,
717                                               ares_dns_rr_key_t    key,
718                                               const size_t       **lenptr)
719 {
720   /* We're going to cast off the const */
721   return ares_dns_rr_data_ptr((void *)((size_t)dns_rr), key,
722                               (void *)((size_t)lenptr));
723 }
724 
ares_dns_rr_get_addr(const ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key)725 const struct in_addr *ares_dns_rr_get_addr(const ares_dns_rr_t *dns_rr,
726                                            ares_dns_rr_key_t    key)
727 {
728   const struct in_addr *addr;
729 
730   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_INADDR) {
731     return NULL;
732   }
733 
734   addr = ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
735   if (addr == NULL) {
736     return NULL;
737   }
738 
739   return addr;
740 }
741 
ares_dns_rr_get_addr6(const ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key)742 const struct ares_in6_addr *ares_dns_rr_get_addr6(const ares_dns_rr_t *dns_rr,
743                                                   ares_dns_rr_key_t    key)
744 {
745   const struct ares_in6_addr *addr;
746 
747   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_INADDR6) {
748     return NULL;
749   }
750 
751   addr = ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
752   if (addr == NULL) {
753     return NULL;
754   }
755 
756   return addr;
757 }
758 
ares_dns_rr_get_u8(const ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key)759 unsigned char ares_dns_rr_get_u8(const ares_dns_rr_t *dns_rr,
760                                  ares_dns_rr_key_t    key)
761 {
762   const unsigned char *u8;
763 
764   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U8) {
765     return 0;
766   }
767 
768   u8 = ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
769   if (u8 == NULL) {
770     return 0;
771   }
772 
773   return *u8;
774 }
775 
ares_dns_rr_get_u16(const ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key)776 unsigned short ares_dns_rr_get_u16(const ares_dns_rr_t *dns_rr,
777                                    ares_dns_rr_key_t    key)
778 {
779   const unsigned short *u16;
780 
781   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U16) {
782     return 0;
783   }
784 
785   u16 = ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
786   if (u16 == NULL) {
787     return 0;
788   }
789 
790   return *u16;
791 }
792 
ares_dns_rr_get_u32(const ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key)793 unsigned int ares_dns_rr_get_u32(const ares_dns_rr_t *dns_rr,
794                                  ares_dns_rr_key_t    key)
795 {
796   const unsigned int *u32;
797 
798   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U32) {
799     return 0;
800   }
801 
802   u32 = ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
803   if (u32 == NULL) {
804     return 0;
805   }
806 
807   return *u32;
808 }
809 
ares_dns_rr_get_bin(const ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,size_t * len)810 const unsigned char *ares_dns_rr_get_bin(const ares_dns_rr_t *dns_rr,
811                                          ares_dns_rr_key_t key, size_t *len)
812 {
813   unsigned char * const *bin     = NULL;
814   size_t const          *bin_len = NULL;
815 
816   if ((ares_dns_rr_key_datatype(key) != ARES_DATATYPE_BIN &&
817        ares_dns_rr_key_datatype(key) != ARES_DATATYPE_BINP) ||
818       len == NULL) {
819     return NULL;
820   }
821 
822   bin = ares_dns_rr_data_ptr_const(dns_rr, key, &bin_len);
823   if (bin == NULL) {
824     return 0;
825   }
826 
827   /* Shouldn't be possible */
828   if (bin_len == NULL) {
829     return NULL;
830   }
831 
832   *len = *bin_len;
833 
834   return *bin;
835 }
836 
ares_dns_rr_get_str(const ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key)837 const char *ares_dns_rr_get_str(const ares_dns_rr_t *dns_rr,
838                                 ares_dns_rr_key_t    key)
839 {
840   char * const *str;
841 
842   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_STR &&
843       ares_dns_rr_key_datatype(key) != ARES_DATATYPE_NAME) {
844     return NULL;
845   }
846 
847   str = ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
848   if (str == NULL) {
849     return NULL;
850   }
851 
852   return *str;
853 }
854 
ares_dns_rr_get_opt_cnt(const ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key)855 size_t ares_dns_rr_get_opt_cnt(const ares_dns_rr_t *dns_rr,
856                                ares_dns_rr_key_t    key)
857 {
858   ares__dns_options_t * const *opts;
859 
860   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_OPT) {
861     return 0;
862   }
863 
864   opts = ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
865   if (opts == NULL || *opts == NULL) {
866     return 0;
867   }
868 
869   return (*opts)->cnt;
870 }
871 
ares_dns_rr_get_opt(const ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,size_t idx,const unsigned char ** val,size_t * val_len)872 unsigned short ares_dns_rr_get_opt(const ares_dns_rr_t *dns_rr,
873                                    ares_dns_rr_key_t key, size_t idx,
874                                    const unsigned char **val, size_t *val_len)
875 {
876   ares__dns_options_t * const *opts;
877 
878   if (val) {
879     *val = NULL;
880   }
881   if (val_len) {
882     *val_len = 0;
883   }
884 
885   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_OPT) {
886     return 65535;
887   }
888 
889   opts = ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
890   if (opts == NULL || *opts == NULL) {
891     return 65535;
892   }
893 
894   if (idx >= (*opts)->cnt) {
895     return 65535;
896   }
897 
898   if (val) {
899     *val = (*opts)->optval[idx].val;
900   }
901   if (val_len) {
902     *val_len = (*opts)->optval[idx].val_len;
903   }
904 
905   return (*opts)->optval[idx].opt;
906 }
907 
ares_dns_rr_get_opt_byid(const ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,unsigned short opt,const unsigned char ** val,size_t * val_len)908 ares_bool_t ares_dns_rr_get_opt_byid(const ares_dns_rr_t *dns_rr,
909                                      ares_dns_rr_key_t key, unsigned short opt,
910                                      const unsigned char **val, size_t *val_len)
911 {
912   ares__dns_options_t * const *opts;
913   size_t                       i;
914 
915   if (val) {
916     *val = NULL;
917   }
918   if (val_len) {
919     *val_len = 0;
920   }
921 
922   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_OPT) {
923     return ARES_FALSE;
924   }
925 
926   opts = ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
927   if (opts == NULL || *opts == NULL) {
928     return ARES_FALSE;
929   }
930 
931   for (i = 0; i < (*opts)->cnt; i++) {
932     if ((*opts)->optval[i].opt == opt) {
933       break;
934     }
935   }
936 
937   if (i >= (*opts)->cnt) {
938     return ARES_FALSE;
939   }
940 
941   if (val) {
942     *val = (*opts)->optval[i].val;
943   }
944   if (val_len) {
945     *val_len = (*opts)->optval[i].val_len;
946   }
947   return ARES_TRUE;
948 }
949 
ares_dns_rr_set_addr(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,const struct in_addr * addr)950 ares_status_t ares_dns_rr_set_addr(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
951                                    const struct in_addr *addr)
952 {
953   struct in_addr *a;
954 
955   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_INADDR || addr == NULL) {
956     return ARES_EFORMERR;
957   }
958 
959   a = ares_dns_rr_data_ptr(dns_rr, key, NULL);
960   if (a == NULL) {
961     return ARES_EFORMERR;
962   }
963 
964   memcpy(a, addr, sizeof(*a));
965   return ARES_SUCCESS;
966 }
967 
ares_dns_rr_set_addr6(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,const struct ares_in6_addr * addr)968 ares_status_t ares_dns_rr_set_addr6(ares_dns_rr_t              *dns_rr,
969                                     ares_dns_rr_key_t           key,
970                                     const struct ares_in6_addr *addr)
971 {
972   struct ares_in6_addr *a;
973 
974   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_INADDR6 || addr == NULL) {
975     return ARES_EFORMERR;
976   }
977 
978   a = ares_dns_rr_data_ptr(dns_rr, key, NULL);
979   if (a == NULL) {
980     return ARES_EFORMERR;
981   }
982 
983   memcpy(a, addr, sizeof(*a));
984   return ARES_SUCCESS;
985 }
986 
ares_dns_rr_set_u8(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,unsigned char val)987 ares_status_t ares_dns_rr_set_u8(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
988                                  unsigned char val)
989 {
990   unsigned char *u8;
991 
992   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U8) {
993     return ARES_EFORMERR;
994   }
995 
996   u8 = ares_dns_rr_data_ptr(dns_rr, key, NULL);
997   if (u8 == NULL) {
998     return ARES_EFORMERR;
999   }
1000 
1001   *u8 = val;
1002   return ARES_SUCCESS;
1003 }
1004 
ares_dns_rr_set_u16(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,unsigned short val)1005 ares_status_t ares_dns_rr_set_u16(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
1006                                   unsigned short val)
1007 {
1008   unsigned short *u16;
1009 
1010   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U16) {
1011     return ARES_EFORMERR;
1012   }
1013 
1014   u16 = ares_dns_rr_data_ptr(dns_rr, key, NULL);
1015   if (u16 == NULL) {
1016     return ARES_EFORMERR;
1017   }
1018 
1019   *u16 = val;
1020   return ARES_SUCCESS;
1021 }
1022 
ares_dns_rr_set_u32(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,unsigned int val)1023 ares_status_t ares_dns_rr_set_u32(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
1024                                   unsigned int val)
1025 {
1026   unsigned int *u32;
1027 
1028   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U32) {
1029     return ARES_EFORMERR;
1030   }
1031 
1032   u32 = ares_dns_rr_data_ptr(dns_rr, key, NULL);
1033   if (u32 == NULL) {
1034     return ARES_EFORMERR;
1035   }
1036 
1037   *u32 = val;
1038   return ARES_SUCCESS;
1039 }
1040 
ares_dns_rr_set_bin_own(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,unsigned char * val,size_t len)1041 ares_status_t ares_dns_rr_set_bin_own(ares_dns_rr_t    *dns_rr,
1042                                       ares_dns_rr_key_t key, unsigned char *val,
1043                                       size_t len)
1044 {
1045   unsigned char **bin;
1046   size_t         *bin_len = NULL;
1047 
1048   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_BIN &&
1049       ares_dns_rr_key_datatype(key) != ARES_DATATYPE_BINP) {
1050     return ARES_EFORMERR;
1051   }
1052 
1053   bin = ares_dns_rr_data_ptr(dns_rr, key, &bin_len);
1054   if (bin == NULL || bin_len == NULL) {
1055     return ARES_EFORMERR;
1056   }
1057 
1058   if (*bin) {
1059     ares_free(*bin);
1060   }
1061   *bin     = val;
1062   *bin_len = len;
1063 
1064   return ARES_SUCCESS;
1065 }
1066 
ares_dns_rr_set_bin(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,const unsigned char * val,size_t len)1067 ares_status_t ares_dns_rr_set_bin(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
1068                                   const unsigned char *val, size_t len)
1069 {
1070   ares_status_t       status;
1071   ares_dns_datatype_t datatype = ares_dns_rr_key_datatype(key);
1072   size_t         alloclen = (datatype == ARES_DATATYPE_BINP) ? len + 1 : len;
1073   unsigned char *temp     = ares_malloc(alloclen);
1074 
1075   if (temp == NULL) {
1076     return ARES_ENOMEM;
1077   }
1078 
1079   memcpy(temp, val, len);
1080 
1081   /* NULL-term BINP */
1082   if (datatype == ARES_DATATYPE_BINP) {
1083     temp[len] = 0;
1084   }
1085 
1086   status = ares_dns_rr_set_bin_own(dns_rr, key, temp, len);
1087   if (status != ARES_SUCCESS) {
1088     ares_free(temp);
1089   }
1090 
1091   return status;
1092 }
1093 
ares_dns_rr_set_str_own(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,char * val)1094 ares_status_t ares_dns_rr_set_str_own(ares_dns_rr_t    *dns_rr,
1095                                       ares_dns_rr_key_t key, char *val)
1096 {
1097   char **str;
1098 
1099   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_STR &&
1100       ares_dns_rr_key_datatype(key) != ARES_DATATYPE_NAME) {
1101     return ARES_EFORMERR;
1102   }
1103 
1104   str = ares_dns_rr_data_ptr(dns_rr, key, NULL);
1105   if (str == NULL) {
1106     return ARES_EFORMERR;
1107   }
1108 
1109   if (*str) {
1110     ares_free(*str);
1111   }
1112   *str = val;
1113 
1114   return ARES_SUCCESS;
1115 }
1116 
ares_dns_rr_set_str(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,const char * val)1117 ares_status_t ares_dns_rr_set_str(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
1118                                   const char *val)
1119 {
1120   ares_status_t status;
1121   char         *temp = NULL;
1122 
1123   if (val != NULL) {
1124     temp = ares_strdup(val);
1125     if (temp == NULL) {
1126       return ARES_ENOMEM;
1127     }
1128   }
1129 
1130   status = ares_dns_rr_set_str_own(dns_rr, key, temp);
1131   if (status != ARES_SUCCESS) {
1132     ares_free(temp);
1133   }
1134 
1135   return status;
1136 }
1137 
ares_dns_rr_set_opt_own(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,unsigned short opt,unsigned char * val,size_t val_len)1138 ares_status_t ares_dns_rr_set_opt_own(ares_dns_rr_t    *dns_rr,
1139                                       ares_dns_rr_key_t key, unsigned short opt,
1140                                       unsigned char *val, size_t val_len)
1141 {
1142   ares__dns_options_t **options;
1143   size_t                idx;
1144 
1145   if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_OPT) {
1146     return ARES_EFORMERR;
1147   }
1148 
1149   options = ares_dns_rr_data_ptr(dns_rr, key, NULL);
1150   if (options == NULL) {
1151     return ARES_EFORMERR;
1152   }
1153 
1154   if (*options == NULL) {
1155     *options = ares_malloc_zero(sizeof(**options));
1156   }
1157   if (*options == NULL) {
1158     return ARES_ENOMEM;
1159   }
1160 
1161   for (idx = 0; idx < (*options)->cnt; idx++) {
1162     if ((*options)->optval[idx].opt == opt) {
1163       break;
1164     }
1165   }
1166 
1167   /* Duplicate entry, replace */
1168   if (idx != (*options)->cnt) {
1169     goto done;
1170   }
1171 
1172   idx = (*options)->cnt;
1173 
1174   /* Expand by powers of 2 */
1175   if (idx >= (*options)->alloc) {
1176     size_t alloc_size = (*options)->alloc;
1177     void  *temp;
1178 
1179     if (alloc_size == 0) {
1180       alloc_size = 1;
1181     } else {
1182       alloc_size <<= 1;
1183     }
1184 
1185     temp = ares_realloc_zero((*options)->optval,
1186                              (*options)->alloc * sizeof(*(*options)->optval),
1187                              alloc_size * sizeof(*(*options)->optval));
1188     if (temp == NULL) {
1189       return ARES_ENOMEM;
1190     }
1191 
1192     (*options)->optval = temp;
1193     (*options)->alloc  = alloc_size;
1194   }
1195 
1196   (*options)->cnt++;
1197 
1198 done:
1199   ares_free((*options)->optval[idx].val);
1200   (*options)->optval[idx].opt     = opt;
1201   (*options)->optval[idx].val     = val;
1202   (*options)->optval[idx].val_len = val_len;
1203 
1204   return ARES_SUCCESS;
1205 }
1206 
ares_dns_rr_set_opt(ares_dns_rr_t * dns_rr,ares_dns_rr_key_t key,unsigned short opt,const unsigned char * val,size_t val_len)1207 ares_status_t ares_dns_rr_set_opt(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
1208                                   unsigned short opt, const unsigned char *val,
1209                                   size_t val_len)
1210 {
1211   unsigned char *temp = NULL;
1212   ares_status_t  status;
1213 
1214   if (val != NULL) {
1215     temp = ares_malloc(val_len + 1);
1216     if (temp == NULL) {
1217       return ARES_ENOMEM;
1218     }
1219     memcpy(temp, val, val_len);
1220     temp[val_len] = 0;
1221   }
1222 
1223   status = ares_dns_rr_set_opt_own(dns_rr, key, opt, temp, val_len);
1224   if (status != ARES_SUCCESS) {
1225     ares_free(temp);
1226   }
1227 
1228   return status;
1229 }
1230 
ares_dns_addr_to_ptr(const struct ares_addr * addr)1231 char *ares_dns_addr_to_ptr(const struct ares_addr *addr)
1232 {
1233   ares__buf_t               *buf     = NULL;
1234   const unsigned char       *ptr     = NULL;
1235   size_t                     ptr_len = 0;
1236   size_t                     i;
1237   ares_status_t              status;
1238   static const unsigned char hexbytes[] = "0123456789abcdef";
1239 
1240   if (addr->family != AF_INET && addr->family != AF_INET6) {
1241     goto fail;
1242   }
1243 
1244   buf = ares__buf_create();
1245   if (buf == NULL) {
1246     goto fail;
1247   }
1248 
1249   if (addr->family == AF_INET) {
1250     ptr     = (const unsigned char *)&addr->addr.addr4;
1251     ptr_len = 4;
1252   } else {
1253     ptr     = (const unsigned char *)&addr->addr.addr6;
1254     ptr_len = 16;
1255   }
1256 
1257   for (i = ptr_len; i > 0; i--) {
1258     if (addr->family == AF_INET) {
1259       status = ares__buf_append_num_dec(buf, (size_t)ptr[i - 1], 0);
1260     } else {
1261       unsigned char c;
1262 
1263       c      = ptr[i - 1] & 0xF;
1264       status = ares__buf_append_byte(buf, hexbytes[c]);
1265       if (status != ARES_SUCCESS) {
1266         goto fail;
1267       }
1268 
1269       status = ares__buf_append_byte(buf, '.');
1270       if (status != ARES_SUCCESS) {
1271         goto fail;
1272       }
1273 
1274       c      = (ptr[i - 1] >> 4) & 0xF;
1275       status = ares__buf_append_byte(buf, hexbytes[c]);
1276     }
1277     if (status != ARES_SUCCESS) {
1278       goto fail;
1279     }
1280 
1281     status = ares__buf_append_byte(buf, '.');
1282     if (status != ARES_SUCCESS) {
1283       goto fail;
1284     }
1285   }
1286 
1287   if (addr->family == AF_INET) {
1288     status = ares__buf_append(buf, (const unsigned char *)"in-addr.arpa", 12);
1289   } else {
1290     status = ares__buf_append(buf, (const unsigned char *)"ip6.arpa", 8);
1291   }
1292   if (status != ARES_SUCCESS) {
1293     goto fail;
1294   }
1295 
1296   return ares__buf_finish_str(buf, NULL);
1297 
1298 fail:
1299   ares__buf_destroy(buf);
1300   return NULL;
1301 }
1302 
1303 /* search for an OPT RR in the response */
ares_dns_has_opt_rr(const ares_dns_record_t * rec)1304 ares_bool_t ares_dns_has_opt_rr(const ares_dns_record_t *rec)
1305 {
1306   size_t i;
1307   for (i = 0; i < ares_dns_record_rr_cnt(rec, ARES_SECTION_ADDITIONAL); i++) {
1308     const ares_dns_rr_t *rr =
1309       ares_dns_record_rr_get_const(rec, ARES_SECTION_ADDITIONAL, i);
1310 
1311     if (ares_dns_rr_get_type(rr) == ARES_REC_TYPE_OPT) {
1312       return ARES_TRUE;
1313     }
1314   }
1315   return ARES_FALSE;
1316 }
1317