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