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
30ares_bool_t ares_dns_opcode_isvalid(ares_dns_opcode_t opcode)
31{
32  switch (opcode) {
33    case ARES_OPCODE_QUERY:
34    case ARES_OPCODE_IQUERY:
35    case ARES_OPCODE_STATUS:
36    case ARES_OPCODE_NOTIFY:
37    case ARES_OPCODE_UPDATE:
38      return ARES_TRUE;
39  }
40  return ARES_FALSE;
41}
42
43ares_bool_t ares_dns_rcode_isvalid(ares_dns_rcode_t rcode)
44{
45  switch (rcode) {
46    case ARES_RCODE_NOERROR:
47    case ARES_RCODE_FORMERR:
48    case ARES_RCODE_SERVFAIL:
49    case ARES_RCODE_NXDOMAIN:
50    case ARES_RCODE_NOTIMP:
51    case ARES_RCODE_REFUSED:
52    case ARES_RCODE_YXDOMAIN:
53    case ARES_RCODE_YXRRSET:
54    case ARES_RCODE_NXRRSET:
55    case ARES_RCODE_NOTAUTH:
56    case ARES_RCODE_NOTZONE:
57    case ARES_RCODE_DSOTYPEI:
58    case ARES_RCODE_BADSIG:
59    case ARES_RCODE_BADKEY:
60    case ARES_RCODE_BADTIME:
61    case ARES_RCODE_BADMODE:
62    case ARES_RCODE_BADNAME:
63    case ARES_RCODE_BADALG:
64    case ARES_RCODE_BADTRUNC:
65    case ARES_RCODE_BADCOOKIE:
66      return ARES_TRUE;
67  }
68  return ARES_FALSE;
69}
70
71ares_bool_t ares_dns_flags_arevalid(unsigned short flags)
72{
73  unsigned short allflags = ARES_FLAG_QR | ARES_FLAG_AA | ARES_FLAG_TC |
74                            ARES_FLAG_RD | ARES_FLAG_RA | ARES_FLAG_AD |
75                            ARES_FLAG_CD;
76
77  if (flags & ~allflags) {
78    return ARES_FALSE;
79  }
80
81  return ARES_TRUE;
82}
83
84ares_bool_t ares_dns_rec_type_isvalid(ares_dns_rec_type_t type,
85                                      ares_bool_t         is_query)
86{
87  switch (type) {
88    case ARES_REC_TYPE_A:
89    case ARES_REC_TYPE_NS:
90    case ARES_REC_TYPE_CNAME:
91    case ARES_REC_TYPE_SOA:
92    case ARES_REC_TYPE_PTR:
93    case ARES_REC_TYPE_HINFO:
94    case ARES_REC_TYPE_MX:
95    case ARES_REC_TYPE_TXT:
96    case ARES_REC_TYPE_AAAA:
97    case ARES_REC_TYPE_SRV:
98    case ARES_REC_TYPE_NAPTR:
99    case ARES_REC_TYPE_OPT:
100    case ARES_REC_TYPE_TLSA:
101    case ARES_REC_TYPE_SVCB:
102    case ARES_REC_TYPE_HTTPS:
103    case ARES_REC_TYPE_ANY:
104    case ARES_REC_TYPE_URI:
105    case ARES_REC_TYPE_CAA:
106      return ARES_TRUE;
107    case ARES_REC_TYPE_RAW_RR:
108      return is_query ? ARES_FALSE : ARES_TRUE;
109    default:
110      break;
111  }
112  return is_query ? ARES_TRUE : ARES_FALSE;
113}
114
115ares_bool_t ares_dns_rec_type_allow_name_compression(ares_dns_rec_type_t type)
116{
117  /* Only record types defined in RFC1035 allow name compression within the
118   * RDATA.  Otherwise nameservers that don't understand an RR may not be
119   * able to pass along the RR in a proper manner */
120  switch (type) {
121    case ARES_REC_TYPE_A:
122    case ARES_REC_TYPE_NS:
123    case ARES_REC_TYPE_CNAME:
124    case ARES_REC_TYPE_SOA:
125    case ARES_REC_TYPE_PTR:
126    case ARES_REC_TYPE_HINFO:
127    case ARES_REC_TYPE_MX:
128    case ARES_REC_TYPE_TXT:
129      return ARES_TRUE;
130    default:
131      break;
132  }
133  return ARES_FALSE;
134}
135
136ares_bool_t ares_dns_class_isvalid(ares_dns_class_t qclass,
137                                   ares_bool_t      is_query)
138{
139  switch (qclass) {
140    case ARES_CLASS_IN:
141    case ARES_CLASS_CHAOS:
142    case ARES_CLASS_HESOID:
143    case ARES_CLASS_NONE:
144      return ARES_TRUE;
145    case ARES_CLASS_ANY:
146      return is_query ? ARES_TRUE : ARES_FALSE;
147  }
148  return ARES_FALSE;
149}
150
151ares_bool_t ares_dns_section_isvalid(ares_dns_section_t sect)
152{
153  switch (sect) {
154    case ARES_SECTION_ANSWER:
155    case ARES_SECTION_AUTHORITY:
156    case ARES_SECTION_ADDITIONAL:
157      return ARES_TRUE;
158  }
159  return ARES_FALSE;
160}
161
162ares_dns_rec_type_t ares_dns_rr_key_to_rec_type(ares_dns_rr_key_t key)
163{
164  /* NOTE: due to the way we've numerated the keys, we can simply divide by
165   *       100 to get the type rather than having to do a huge switch
166   *       statement.  That said, we do then validate the type returned is
167   *       valid in case something completely bogus is passed in */
168  ares_dns_rec_type_t type = key / 100;
169  if (!ares_dns_rec_type_isvalid(type, ARES_FALSE)) {
170    return 0;
171  }
172  return type;
173}
174
175const char *ares_dns_rec_type_tostr(ares_dns_rec_type_t type)
176{
177  switch (type) {
178    case ARES_REC_TYPE_A:
179      return "A";
180    case ARES_REC_TYPE_NS:
181      return "NS";
182    case ARES_REC_TYPE_CNAME:
183      return "CNAME";
184    case ARES_REC_TYPE_SOA:
185      return "SOA";
186    case ARES_REC_TYPE_PTR:
187      return "PTR";
188    case ARES_REC_TYPE_HINFO:
189      return "HINFO";
190    case ARES_REC_TYPE_MX:
191      return "MX";
192    case ARES_REC_TYPE_TXT:
193      return "TXT";
194    case ARES_REC_TYPE_AAAA:
195      return "AAAA";
196    case ARES_REC_TYPE_SRV:
197      return "SRV";
198    case ARES_REC_TYPE_NAPTR:
199      return "NAPTR";
200    case ARES_REC_TYPE_OPT:
201      return "OPT";
202    case ARES_REC_TYPE_TLSA:
203      return "TLSA";
204    case ARES_REC_TYPE_SVCB:
205      return "SVCB";
206    case ARES_REC_TYPE_HTTPS:
207      return "HTTPS";
208    case ARES_REC_TYPE_ANY:
209      return "ANY";
210    case ARES_REC_TYPE_URI:
211      return "URI";
212    case ARES_REC_TYPE_CAA:
213      return "CAA";
214    case ARES_REC_TYPE_RAW_RR:
215      return "RAWRR";
216  }
217  return "UNKNOWN";
218}
219
220const char *ares_dns_class_tostr(ares_dns_class_t qclass)
221{
222  switch (qclass) {
223    case ARES_CLASS_IN:
224      return "IN";
225    case ARES_CLASS_CHAOS:
226      return "CH";
227    case ARES_CLASS_HESOID:
228      return "HS";
229    case ARES_CLASS_ANY:
230      return "ANY";
231    case ARES_CLASS_NONE:
232      return "NONE";
233  }
234  return "UNKNOWN";
235}
236
237const char *ares_dns_opcode_tostr(ares_dns_opcode_t opcode)
238{
239  switch (opcode) {
240    case ARES_OPCODE_QUERY:
241      return "QUERY";
242    case ARES_OPCODE_IQUERY:
243      return "IQUERY";
244    case ARES_OPCODE_STATUS:
245      return "STATUS";
246    case ARES_OPCODE_NOTIFY:
247      return "NOTIFY";
248    case ARES_OPCODE_UPDATE:
249      return "UPDATE";
250  }
251  return "UNKNOWN";
252}
253
254const char *ares_dns_rr_key_tostr(ares_dns_rr_key_t key)
255{
256  switch (key) {
257    case ARES_RR_A_ADDR:
258      return "ADDR";
259
260    case ARES_RR_NS_NSDNAME:
261      return "NSDNAME";
262
263    case ARES_RR_CNAME_CNAME:
264      return "CNAME";
265
266    case ARES_RR_SOA_MNAME:
267      return "MNAME";
268
269    case ARES_RR_SOA_RNAME:
270      return "RNAME";
271
272    case ARES_RR_SOA_SERIAL:
273      return "SERIAL";
274
275    case ARES_RR_SOA_REFRESH:
276      return "REFRESH";
277
278    case ARES_RR_SOA_RETRY:
279      return "RETRY";
280
281    case ARES_RR_SOA_EXPIRE:
282      return "EXPIRE";
283
284    case ARES_RR_SOA_MINIMUM:
285      return "MINIMUM";
286
287    case ARES_RR_PTR_DNAME:
288      return "DNAME";
289
290    case ARES_RR_AAAA_ADDR:
291      return "ADDR";
292
293    case ARES_RR_HINFO_CPU:
294      return "CPU";
295
296    case ARES_RR_HINFO_OS:
297      return "OS";
298
299    case ARES_RR_MX_PREFERENCE:
300      return "PREFERENCE";
301
302    case ARES_RR_MX_EXCHANGE:
303      return "EXCHANGE";
304
305    case ARES_RR_TXT_DATA:
306      return "DATA";
307
308    case ARES_RR_SRV_PRIORITY:
309      return "PRIORITY";
310
311    case ARES_RR_SRV_WEIGHT:
312      return "WEIGHT";
313
314    case ARES_RR_SRV_PORT:
315      return "PORT";
316
317    case ARES_RR_SRV_TARGET:
318      return "TARGET";
319
320    case ARES_RR_NAPTR_ORDER:
321      return "ORDER";
322
323    case ARES_RR_NAPTR_PREFERENCE:
324      return "PREFERENCE";
325
326    case ARES_RR_NAPTR_FLAGS:
327      return "FLAGS";
328
329    case ARES_RR_NAPTR_SERVICES:
330      return "SERVICES";
331
332    case ARES_RR_NAPTR_REGEXP:
333      return "REGEXP";
334
335    case ARES_RR_NAPTR_REPLACEMENT:
336      return "REPLACEMENT";
337
338    case ARES_RR_OPT_UDP_SIZE:
339      return "UDP_SIZE";
340
341    case ARES_RR_OPT_VERSION:
342      return "VERSION";
343
344    case ARES_RR_OPT_FLAGS:
345      return "FLAGS";
346
347    case ARES_RR_OPT_OPTIONS:
348      return "OPTIONS";
349
350    case ARES_RR_TLSA_CERT_USAGE:
351      return "CERT_USAGE";
352
353    case ARES_RR_TLSA_SELECTOR:
354      return "SELECTOR";
355
356    case ARES_RR_TLSA_MATCH:
357      return "MATCH";
358
359    case ARES_RR_TLSA_DATA:
360      return "DATA";
361
362    case ARES_RR_SVCB_PRIORITY:
363      return "PRIORITY";
364
365    case ARES_RR_SVCB_TARGET:
366      return "TARGET";
367
368    case ARES_RR_SVCB_PARAMS:
369      return "PARAMS";
370
371    case ARES_RR_HTTPS_PRIORITY:
372      return "PRIORITY";
373
374    case ARES_RR_HTTPS_TARGET:
375      return "TARGET";
376
377    case ARES_RR_HTTPS_PARAMS:
378      return "PARAMS";
379
380    case ARES_RR_URI_PRIORITY:
381      return "PRIORITY";
382
383    case ARES_RR_URI_WEIGHT:
384      return "WEIGHT";
385
386    case ARES_RR_URI_TARGET:
387      return "TARGET";
388
389    case ARES_RR_CAA_CRITICAL:
390      return "CRITICAL";
391
392    case ARES_RR_CAA_TAG:
393      return "TAG";
394
395    case ARES_RR_CAA_VALUE:
396      return "VALUE";
397
398    case ARES_RR_RAW_RR_TYPE:
399      return "TYPE";
400
401    case ARES_RR_RAW_RR_DATA:
402      return "DATA";
403  }
404
405  return "UNKNOWN";
406}
407
408ares_dns_datatype_t ares_dns_rr_key_datatype(ares_dns_rr_key_t key)
409{
410  switch (key) {
411    case ARES_RR_A_ADDR:
412      return ARES_DATATYPE_INADDR;
413
414    case ARES_RR_AAAA_ADDR:
415      return ARES_DATATYPE_INADDR6;
416
417    case ARES_RR_NS_NSDNAME:
418    case ARES_RR_CNAME_CNAME:
419    case ARES_RR_SOA_MNAME:
420    case ARES_RR_SOA_RNAME:
421    case ARES_RR_PTR_DNAME:
422    case ARES_RR_MX_EXCHANGE:
423    case ARES_RR_SRV_TARGET:
424    case ARES_RR_SVCB_TARGET:
425    case ARES_RR_HTTPS_TARGET:
426    case ARES_RR_NAPTR_REPLACEMENT:
427    case ARES_RR_URI_TARGET:
428      return ARES_DATATYPE_NAME;
429
430    case ARES_RR_HINFO_CPU:
431    case ARES_RR_HINFO_OS:
432    case ARES_RR_NAPTR_FLAGS:
433    case ARES_RR_NAPTR_SERVICES:
434    case ARES_RR_NAPTR_REGEXP:
435    case ARES_RR_CAA_TAG:
436      return ARES_DATATYPE_STR;
437
438    case ARES_RR_SOA_SERIAL:
439    case ARES_RR_SOA_REFRESH:
440    case ARES_RR_SOA_RETRY:
441    case ARES_RR_SOA_EXPIRE:
442    case ARES_RR_SOA_MINIMUM:
443      return ARES_DATATYPE_U32;
444
445    case ARES_RR_MX_PREFERENCE:
446    case ARES_RR_SRV_PRIORITY:
447    case ARES_RR_SRV_WEIGHT:
448    case ARES_RR_SRV_PORT:
449    case ARES_RR_NAPTR_ORDER:
450    case ARES_RR_NAPTR_PREFERENCE:
451    case ARES_RR_OPT_UDP_SIZE:
452    case ARES_RR_OPT_FLAGS:
453    case ARES_RR_SVCB_PRIORITY:
454    case ARES_RR_HTTPS_PRIORITY:
455    case ARES_RR_URI_PRIORITY:
456    case ARES_RR_URI_WEIGHT:
457    case ARES_RR_RAW_RR_TYPE:
458      return ARES_DATATYPE_U16;
459
460    case ARES_RR_OPT_VERSION:
461    case ARES_RR_TLSA_CERT_USAGE:
462    case ARES_RR_TLSA_SELECTOR:
463    case ARES_RR_TLSA_MATCH:
464    case ARES_RR_CAA_CRITICAL:
465      return ARES_DATATYPE_U8;
466
467    case ARES_RR_CAA_VALUE:
468    case ARES_RR_TXT_DATA:
469      return ARES_DATATYPE_BINP;
470
471    case ARES_RR_TLSA_DATA:
472    case ARES_RR_RAW_RR_DATA:
473      return ARES_DATATYPE_BIN;
474
475    case ARES_RR_OPT_OPTIONS:
476    case ARES_RR_SVCB_PARAMS:
477    case ARES_RR_HTTPS_PARAMS:
478      return ARES_DATATYPE_OPT;
479  }
480
481  return 0;
482}
483
484static const ares_dns_rr_key_t rr_a_keys[]     = { ARES_RR_A_ADDR };
485static const ares_dns_rr_key_t rr_ns_keys[]    = { ARES_RR_NS_NSDNAME };
486static const ares_dns_rr_key_t rr_cname_keys[] = { ARES_RR_CNAME_CNAME };
487static const ares_dns_rr_key_t rr_soa_keys[]   = {
488  ARES_RR_SOA_MNAME,   ARES_RR_SOA_RNAME, ARES_RR_SOA_SERIAL,
489  ARES_RR_SOA_REFRESH, ARES_RR_SOA_RETRY, ARES_RR_SOA_EXPIRE,
490  ARES_RR_SOA_MINIMUM
491};
492static const ares_dns_rr_key_t rr_ptr_keys[]   = { ARES_RR_PTR_DNAME };
493static const ares_dns_rr_key_t rr_hinfo_keys[] = { ARES_RR_HINFO_CPU,
494                                                   ARES_RR_HINFO_OS };
495static const ares_dns_rr_key_t rr_mx_keys[]    = { ARES_RR_MX_PREFERENCE,
496                                                   ARES_RR_MX_EXCHANGE };
497static const ares_dns_rr_key_t rr_txt_keys[]   = { ARES_RR_TXT_DATA };
498static const ares_dns_rr_key_t rr_aaaa_keys[]  = { ARES_RR_AAAA_ADDR };
499static const ares_dns_rr_key_t rr_srv_keys[]   = {
500  ARES_RR_SRV_PRIORITY, ARES_RR_SRV_WEIGHT, ARES_RR_SRV_PORT, ARES_RR_SRV_TARGET
501};
502static const ares_dns_rr_key_t rr_naptr_keys[] = {
503  ARES_RR_NAPTR_ORDER,    ARES_RR_NAPTR_PREFERENCE, ARES_RR_NAPTR_FLAGS,
504  ARES_RR_NAPTR_SERVICES, ARES_RR_NAPTR_REGEXP,     ARES_RR_NAPTR_REPLACEMENT
505};
506static const ares_dns_rr_key_t rr_opt_keys[]    = { ARES_RR_OPT_UDP_SIZE,
507                                                    ARES_RR_OPT_VERSION,
508                                                    ARES_RR_OPT_FLAGS,
509                                                    ARES_RR_OPT_OPTIONS };
510static const ares_dns_rr_key_t rr_tlsa_keys[]   = { ARES_RR_TLSA_CERT_USAGE,
511                                                    ARES_RR_TLSA_SELECTOR,
512                                                    ARES_RR_TLSA_MATCH,
513                                                    ARES_RR_TLSA_DATA };
514static const ares_dns_rr_key_t rr_svcb_keys[]   = { ARES_RR_SVCB_PRIORITY,
515                                                    ARES_RR_SVCB_TARGET,
516                                                    ARES_RR_SVCB_PARAMS };
517static const ares_dns_rr_key_t rr_https_keys[]  = { ARES_RR_HTTPS_PRIORITY,
518                                                    ARES_RR_HTTPS_TARGET,
519                                                    ARES_RR_HTTPS_PARAMS };
520static const ares_dns_rr_key_t rr_uri_keys[]    = { ARES_RR_URI_PRIORITY,
521                                                    ARES_RR_URI_WEIGHT,
522                                                    ARES_RR_URI_TARGET };
523static const ares_dns_rr_key_t rr_caa_keys[]    = { ARES_RR_CAA_CRITICAL,
524                                                    ARES_RR_CAA_TAG,
525                                                    ARES_RR_CAA_VALUE };
526static const ares_dns_rr_key_t rr_raw_rr_keys[] = { ARES_RR_RAW_RR_TYPE,
527                                                    ARES_RR_RAW_RR_DATA };
528
529const ares_dns_rr_key_t       *ares_dns_rr_get_keys(ares_dns_rec_type_t type,
530                                                    size_t             *cnt)
531{
532  if (cnt == NULL) {
533    return NULL;
534  }
535
536  *cnt = 0;
537
538  switch (type) {
539    case ARES_REC_TYPE_A:
540      *cnt = sizeof(rr_a_keys) / sizeof(*rr_a_keys);
541      return rr_a_keys;
542    case ARES_REC_TYPE_NS:
543      *cnt = sizeof(rr_ns_keys) / sizeof(*rr_ns_keys);
544      return rr_ns_keys;
545    case ARES_REC_TYPE_CNAME:
546      *cnt = sizeof(rr_cname_keys) / sizeof(*rr_cname_keys);
547      return rr_cname_keys;
548    case ARES_REC_TYPE_SOA:
549      *cnt = sizeof(rr_soa_keys) / sizeof(*rr_soa_keys);
550      return rr_soa_keys;
551    case ARES_REC_TYPE_PTR:
552      *cnt = sizeof(rr_ptr_keys) / sizeof(*rr_ptr_keys);
553      return rr_ptr_keys;
554    case ARES_REC_TYPE_HINFO:
555      *cnt = sizeof(rr_hinfo_keys) / sizeof(*rr_hinfo_keys);
556      return rr_hinfo_keys;
557    case ARES_REC_TYPE_MX:
558      *cnt = sizeof(rr_mx_keys) / sizeof(*rr_mx_keys);
559      return rr_mx_keys;
560    case ARES_REC_TYPE_TXT:
561      *cnt = sizeof(rr_txt_keys) / sizeof(*rr_txt_keys);
562      return rr_txt_keys;
563    case ARES_REC_TYPE_AAAA:
564      *cnt = sizeof(rr_aaaa_keys) / sizeof(*rr_aaaa_keys);
565      return rr_aaaa_keys;
566    case ARES_REC_TYPE_SRV:
567      *cnt = sizeof(rr_srv_keys) / sizeof(*rr_srv_keys);
568      return rr_srv_keys;
569    case ARES_REC_TYPE_NAPTR:
570      *cnt = sizeof(rr_naptr_keys) / sizeof(*rr_naptr_keys);
571      return rr_naptr_keys;
572    case ARES_REC_TYPE_OPT:
573      *cnt = sizeof(rr_opt_keys) / sizeof(*rr_opt_keys);
574      return rr_opt_keys;
575    case ARES_REC_TYPE_TLSA:
576      *cnt = sizeof(rr_tlsa_keys) / sizeof(*rr_tlsa_keys);
577      return rr_tlsa_keys;
578    case ARES_REC_TYPE_SVCB:
579      *cnt = sizeof(rr_svcb_keys) / sizeof(*rr_svcb_keys);
580      return rr_svcb_keys;
581    case ARES_REC_TYPE_HTTPS:
582      *cnt = sizeof(rr_https_keys) / sizeof(*rr_https_keys);
583      return rr_https_keys;
584    case ARES_REC_TYPE_ANY:
585      /* Not real */
586      break;
587    case ARES_REC_TYPE_URI:
588      *cnt = sizeof(rr_uri_keys) / sizeof(*rr_uri_keys);
589      return rr_uri_keys;
590    case ARES_REC_TYPE_CAA:
591      *cnt = sizeof(rr_caa_keys) / sizeof(*rr_caa_keys);
592      return rr_caa_keys;
593    case ARES_REC_TYPE_RAW_RR:
594      *cnt = sizeof(rr_raw_rr_keys) / sizeof(*rr_raw_rr_keys);
595      return rr_raw_rr_keys;
596  }
597
598  return NULL;
599}
600
601ares_bool_t ares_dns_class_fromstr(ares_dns_class_t *qclass, const char *str)
602{
603  size_t i;
604
605  static const struct {
606    const char      *name;
607    ares_dns_class_t qclass;
608  } list[] = {
609    {"IN",    ARES_CLASS_IN    },
610    { "CH",   ARES_CLASS_CHAOS },
611    { "HS",   ARES_CLASS_HESOID},
612    { "NONE", ARES_CLASS_NONE  },
613    { "ANY",  ARES_CLASS_ANY   },
614    { NULL,   0                }
615  };
616
617  if (qclass == NULL || str == NULL) {
618    return ARES_FALSE;
619  }
620
621  for (i = 0; list[i].name != NULL; i++) {
622    if (strcasecmp(list[i].name, str) == 0) {
623      *qclass = list[i].qclass;
624      return ARES_TRUE;
625    }
626  }
627  return ARES_FALSE;
628}
629
630ares_bool_t ares_dns_rec_type_fromstr(ares_dns_rec_type_t *qtype,
631                                      const char          *str)
632{
633  size_t i;
634
635  static const struct {
636    const char         *name;
637    ares_dns_rec_type_t type;
638  } list[] = {
639    {"A",       ARES_REC_TYPE_A     },
640    { "NS",     ARES_REC_TYPE_NS    },
641    { "CNAME",  ARES_REC_TYPE_CNAME },
642    { "SOA",    ARES_REC_TYPE_SOA   },
643    { "PTR",    ARES_REC_TYPE_PTR   },
644    { "HINFO",  ARES_REC_TYPE_HINFO },
645    { "MX",     ARES_REC_TYPE_MX    },
646    { "TXT",    ARES_REC_TYPE_TXT   },
647    { "AAAA",   ARES_REC_TYPE_AAAA  },
648    { "SRV",    ARES_REC_TYPE_SRV   },
649    { "NAPTR",  ARES_REC_TYPE_NAPTR },
650    { "OPT",    ARES_REC_TYPE_OPT   },
651    { "TLSA",   ARES_REC_TYPE_TLSA  },
652    { "SVCB",   ARES_REC_TYPE_SVCB  },
653    { "HTTPS",  ARES_REC_TYPE_HTTPS },
654    { "ANY",    ARES_REC_TYPE_ANY   },
655    { "URI",    ARES_REC_TYPE_URI   },
656    { "CAA",    ARES_REC_TYPE_CAA   },
657    { "RAW_RR", ARES_REC_TYPE_RAW_RR},
658    { NULL,     0                   }
659  };
660
661  if (qtype == NULL || str == NULL) {
662    return ARES_FALSE;
663  }
664
665  for (i = 0; list[i].name != NULL; i++) {
666    if (strcasecmp(list[i].name, str) == 0) {
667      *qtype = list[i].type;
668      return ARES_TRUE;
669    }
670  }
671  return ARES_FALSE;
672}
673
674const char *ares_dns_section_tostr(ares_dns_section_t section)
675{
676  switch (section) {
677    case ARES_SECTION_ANSWER:
678      return "ANSWER";
679    case ARES_SECTION_AUTHORITY:
680      return "AUTHORITY";
681    case ARES_SECTION_ADDITIONAL:
682      return "ADDITIONAL";
683  }
684  return "UNKNOWN";
685}
686
687static ares_dns_opt_datatype_t ares_dns_opt_get_type_opt(unsigned short opt)
688{
689  ares_opt_param_t param = (ares_opt_param_t)opt;
690  switch (param) {
691    case ARES_OPT_PARAM_LLQ:
692      /* Really it is u16 version, u16 opcode, u16 error, u64 id, u32 lease */
693      return ARES_OPT_DATATYPE_BIN;
694    case ARES_OPT_PARAM_UL:
695      return ARES_OPT_DATATYPE_U32;
696    case ARES_OPT_PARAM_NSID:
697      return ARES_OPT_DATATYPE_BIN;
698    case ARES_OPT_PARAM_DAU:
699      return ARES_OPT_DATATYPE_U8_LIST;
700    case ARES_OPT_PARAM_DHU:
701      return ARES_OPT_DATATYPE_U8_LIST;
702    case ARES_OPT_PARAM_N3U:
703      return ARES_OPT_DATATYPE_U8_LIST;
704    case ARES_OPT_PARAM_EDNS_CLIENT_SUBNET:
705      /* Really it is a u16 address family, u8 source prefix length,
706       * u8 scope prefix length, address */
707      return ARES_OPT_DATATYPE_BIN;
708    case ARES_OPT_PARAM_EDNS_EXPIRE:
709      return ARES_OPT_DATATYPE_U32;
710    case ARES_OPT_PARAM_COOKIE:
711      /* 8 bytes for client, 16-40 bytes for server */
712      return ARES_OPT_DATATYPE_BIN;
713    case ARES_OPT_PARAM_EDNS_TCP_KEEPALIVE:
714      /* Timeout in 100ms intervals */
715      return ARES_OPT_DATATYPE_U16;
716    case ARES_OPT_PARAM_PADDING:
717      /* Arbitrary padding */
718      return ARES_OPT_DATATYPE_BIN;
719    case ARES_OPT_PARAM_CHAIN:
720      return ARES_OPT_DATATYPE_NAME;
721    case ARES_OPT_PARAM_EDNS_KEY_TAG:
722      return ARES_OPT_DATATYPE_U16_LIST;
723    case ARES_OPT_PARAM_EXTENDED_DNS_ERROR:
724      /* Really 16bit code followed by textual message */
725      return ARES_OPT_DATATYPE_BIN;
726  }
727  return ARES_OPT_DATATYPE_BIN;
728}
729
730static ares_dns_opt_datatype_t ares_dns_opt_get_type_svcb(unsigned short opt)
731{
732  ares_svcb_param_t param = (ares_svcb_param_t)opt;
733  switch (param) {
734    case ARES_SVCB_PARAM_NO_DEFAULT_ALPN:
735      return ARES_OPT_DATATYPE_NONE;
736    case ARES_SVCB_PARAM_ECH:
737      return ARES_OPT_DATATYPE_BIN;
738    case ARES_SVCB_PARAM_MANDATORY:
739      return ARES_OPT_DATATYPE_U16_LIST;
740    case ARES_SVCB_PARAM_ALPN:
741      return ARES_OPT_DATATYPE_STR_LIST;
742    case ARES_SVCB_PARAM_PORT:
743      return ARES_OPT_DATATYPE_U16;
744    case ARES_SVCB_PARAM_IPV4HINT:
745      return ARES_OPT_DATATYPE_INADDR4_LIST;
746    case ARES_SVCB_PARAM_IPV6HINT:
747      return ARES_OPT_DATATYPE_INADDR6_LIST;
748  }
749  return ARES_OPT_DATATYPE_BIN;
750}
751
752ares_dns_opt_datatype_t ares_dns_opt_get_datatype(ares_dns_rr_key_t key,
753                                                  unsigned short    opt)
754{
755  switch (key) {
756    case ARES_RR_OPT_OPTIONS:
757      return ares_dns_opt_get_type_opt(opt);
758    case ARES_RR_SVCB_PARAMS:
759    case ARES_RR_HTTPS_PARAMS:
760      return ares_dns_opt_get_type_svcb(opt);
761    default:
762      break;
763  }
764  return ARES_OPT_DATATYPE_BIN;
765}
766
767static const char *ares_dns_opt_get_name_opt(unsigned short opt)
768{
769  ares_opt_param_t param = (ares_opt_param_t)opt;
770  switch (param) {
771    case ARES_OPT_PARAM_LLQ:
772      return "LLQ";
773    case ARES_OPT_PARAM_UL:
774      return "UL";
775    case ARES_OPT_PARAM_NSID:
776      return "NSID";
777    case ARES_OPT_PARAM_DAU:
778      return "DAU";
779    case ARES_OPT_PARAM_DHU:
780      return "DHU";
781    case ARES_OPT_PARAM_N3U:
782      return "N3U";
783    case ARES_OPT_PARAM_EDNS_CLIENT_SUBNET:
784      return "edns-client-subnet";
785    case ARES_OPT_PARAM_EDNS_EXPIRE:
786      return "edns-expire";
787    case ARES_OPT_PARAM_COOKIE:
788      return "COOKIE";
789    case ARES_OPT_PARAM_EDNS_TCP_KEEPALIVE:
790      return "edns-tcp-keepalive";
791    case ARES_OPT_PARAM_PADDING:
792      return "Padding";
793    case ARES_OPT_PARAM_CHAIN:
794      return "CHAIN";
795    case ARES_OPT_PARAM_EDNS_KEY_TAG:
796      return "edns-key-tag";
797    case ARES_OPT_PARAM_EXTENDED_DNS_ERROR:
798      return "extended-dns-error";
799  }
800  return NULL;
801}
802
803static const char *ares_dns_opt_get_name_svcb(unsigned short opt)
804{
805  ares_svcb_param_t param = (ares_svcb_param_t)opt;
806  switch (param) {
807    case ARES_SVCB_PARAM_NO_DEFAULT_ALPN:
808      return "no-default-alpn";
809    case ARES_SVCB_PARAM_ECH:
810      return "ech";
811    case ARES_SVCB_PARAM_MANDATORY:
812      return "mandatory";
813    case ARES_SVCB_PARAM_ALPN:
814      return "alpn";
815    case ARES_SVCB_PARAM_PORT:
816      return "port";
817    case ARES_SVCB_PARAM_IPV4HINT:
818      return "ipv4hint";
819    case ARES_SVCB_PARAM_IPV6HINT:
820      return "ipv6hint";
821  }
822  return NULL;
823}
824
825const char *ares_dns_opt_get_name(ares_dns_rr_key_t key, unsigned short opt)
826{
827  switch (key) {
828    case ARES_RR_OPT_OPTIONS:
829      return ares_dns_opt_get_name_opt(opt);
830    case ARES_RR_SVCB_PARAMS:
831    case ARES_RR_HTTPS_PARAMS:
832      return ares_dns_opt_get_name_svcb(opt);
833    default:
834      break;
835  }
836  return NULL;
837}
838
839const char *ares_dns_rcode_tostr(ares_dns_rcode_t rcode)
840{
841  switch (rcode) {
842    case ARES_RCODE_NOERROR:
843      return "NOERROR";
844    case ARES_RCODE_FORMERR:
845      return "FORMERR";
846    case ARES_RCODE_SERVFAIL:
847      return "SERVFAIL";
848    case ARES_RCODE_NXDOMAIN:
849      return "NXDOMAIN";
850    case ARES_RCODE_NOTIMP:
851      return "NOTIMP";
852    case ARES_RCODE_REFUSED:
853      return "REFUSED";
854    case ARES_RCODE_YXDOMAIN:
855      return "YXDOMAIN";
856    case ARES_RCODE_YXRRSET:
857      return "YXRRSET";
858    case ARES_RCODE_NXRRSET:
859      return "NXRRSET";
860    case ARES_RCODE_NOTAUTH:
861      return "NOTAUTH";
862    case ARES_RCODE_NOTZONE:
863      return "NOTZONE";
864    case ARES_RCODE_DSOTYPEI:
865      return "DSOTYPEI";
866    case ARES_RCODE_BADSIG:
867      return "BADSIG";
868    case ARES_RCODE_BADKEY:
869      return "BADKEY";
870    case ARES_RCODE_BADTIME:
871      return "BADTIME";
872    case ARES_RCODE_BADMODE:
873      return "BADMODE";
874    case ARES_RCODE_BADNAME:
875      return "BADNAME";
876    case ARES_RCODE_BADALG:
877      return "BADALG";
878    case ARES_RCODE_BADTRUNC:
879      return "BADTRUNC";
880    case ARES_RCODE_BADCOOKIE:
881      return "BADCOOKIE";
882  }
883
884  return "UNKNOWN";
885}
886