1 /*        $NetBSD: dns.h,v 1.7 2025/02/25 19:15:44 christos Exp $     */
2 
3 #ifndef _DNS_H_INCLUDED_
4 #define _DNS_H_INCLUDED_
5 
6 /*++
7 /* NAME
8 /*        dns 3h
9 /* SUMMARY
10 /*        domain name service lookup
11 /* SYNOPSIS
12 /*        #include <dns.h>
13 /* DESCRIPTION
14 /* .nf
15 
16  /*
17   * System library.
18   */
19 #include <netinet/in.h>
20 #include <arpa/nameser.h>
21 #ifdef RESOLVE_H_NEEDS_STDIO_H
22 #include <stdio.h>
23 #endif
24 #ifdef RESOLVE_H_NEEDS_NAMESER8_COMPAT_H
25 #include <nameser8_compat.h>
26 #endif
27 #ifdef RESOLVE_H_NEEDS_ARPA_NAMESER_COMPAT_H
28 #include <arpa/nameser_compat.h>
29 #endif
30 #include <resolv.h>
31 
32  /*
33   * Name server compatibility. These undocumented macros appear in the file
34   * <arpa/nameser.h>, but since they are undocumented we should not count on
35   * their presence, and so they are included here just in case.
36   */
37 #ifndef GETSHORT
38 
39 #define GETSHORT(s, cp) { \
40           unsigned char *t_cp = (u_char *)(cp); \
41           (s) = ((unsigned)t_cp[0] << 8) \
42               | ((unsigned)t_cp[1]) \
43               ; \
44           (cp) += 2; \
45 }
46 
47 #define GETLONG(l, cp) { \
48           unsigned char *t_cp = (u_char *)(cp); \
49           (l) = ((unsigned)t_cp[0] << 24) \
50               | ((unsigned)t_cp[1] << 16) \
51               | ((unsigned)t_cp[2] << 8) \
52               | ((unsigned)t_cp[3]) \
53               ; \
54           (cp) += 4; \
55 }
56 
57 #endif
58 
59  /*
60   * Provide API compatibility for systems without res_nxxx() API. Also
61   * require calling dns_get_h_errno() instead of directly accessing the
62   * global h_errno variable. We should not count on that being updated.
63   */
64 #if !defined(NO_RES_NCALLS) && defined(__RES) && (__RES >= 19991006)
65 #define USE_RES_NCALLS
66 #undef h_errno
67 #define h_errno use_dns_get_h_errno_instead_of_h_errno
68 #endif
69 
70 /*
71  * Disable DNSSEC at compile-time even if RES_USE_DNSSEC is available
72  */
73 #ifdef NO_DNSSEC
74 #undef RES_USE_DNSSEC
75 #undef RES_TRUSTAD
76 #endif
77 
78  /*
79   * Compatibility with systems that lack RES_USE_DNSSEC and RES_USE_EDNS0
80   */
81 #ifndef RES_USE_DNSSEC
82 #define RES_USE_DNSSEC        0
83 #endif
84 #ifndef RES_USE_EDNS0
85 #define RES_USE_EDNS0         0
86 #endif
87 #ifndef RES_TRUSTAD
88 #define RES_TRUSTAD 0
89 #endif
90 
91  /*-
92   * TLSA: https://tools.ietf.org/html/rfc6698#section-7.1
93   * RRSIG: https://tools.ietf.org/html/rfc4034#section-3
94   *
95   * We don't request RRSIG, but we get it "for free" when we send the DO-bit.
96   */
97 #ifndef T_TLSA
98 #define T_TLSA                52
99 #endif
100 #ifndef T_RRSIG
101 #define T_RRSIG               46                  /* Avoid unknown RR in logs */
102 #endif
103 #ifndef T_DNAME
104 #define T_DNAME               39                  /* [RFC6672] */
105 #endif
106 
107  /*
108   * https://tools.ietf.org/html/rfc6698#section-7.2
109   */
110 #define DNS_TLSA_USAGE_CA_CONSTRAINT                        0
111 #define DNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT       1
112 #define DNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION               2
113 #define DNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE  3
114 
115  /*
116   * https://tools.ietf.org/html/rfc6698#section-7.3
117   */
118 #define DNS_TLSA_SELECTOR_FULL_CERTIFICATE        0
119 #define DNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO    1
120 
121  /*
122   * https://tools.ietf.org/html/rfc6698#section-7.4
123   */
124 #define DNS_TLSA_MATCHING_TYPE_NO_HASH_USED       0
125 #define DNS_TLSA_MATCHING_TYPE_SHA256             1
126 #define DNS_TLSA_MATCHING_TYPE_SHA512             2
127 
128  /*
129   * SunOS 4 needs this.
130   */
131 #ifndef T_TXT
132 #define T_TXT       16
133 #endif
134 
135  /*
136   * Utility library.
137   */
138 #include <vstring.h>
139 #include <sock_addr.h>
140 #include <myaddrinfo.h>
141 
142  /*
143   * Structure for fixed resource record data.
144   */
145 typedef struct DNS_FIXED {
146     unsigned short type;                /* T_A, T_CNAME, etc. */
147     unsigned short class;               /* C_IN, etc. */
148     unsigned int ttl;                             /* always */
149     unsigned length;                              /* record length */
150 } DNS_FIXED;
151 
152  /*
153   * Structure of a DNS resource record after expansion. The components are
154   * named after the things one can expect to find in a DNS resource record.
155   */
156 typedef struct DNS_RR {
157     char   *qname;                      /* query name, mystrdup()ed */
158     char   *rname;                      /* reply name, mystrdup()ed */
159     unsigned short type;                /* T_A, T_CNAME, etc. */
160     unsigned short class;               /* C_IN, etc. */
161     unsigned int ttl;                             /* always */
162     unsigned int dnssec_valid;                    /* DNSSEC validated */
163     unsigned short pref;                /* T_MX and T_SRV record related */
164     unsigned short weight;              /* T_SRV related, defined in rfc2782 */
165     unsigned short port;                /* T_SRV related, defined in rfc2782 */
166     /* Assume that flags lives in what was previously padding */
167     unsigned short flags;               /* DNS_RR_FLAG_XX, see below */
168     struct DNS_RR *next;                /* linkage */
169     size_t  data_len;                             /* actual data size */
170     char   *data;                       /* a bunch of data */
171     /* Add new fields at the end, for ABI forward compatibility. */
172 } DNS_RR;
173 
174 #define DNS_RR_FLAG_TRUNCATED (1<<0)
175 
176 #define DNS_RR_IS_TRUNCATED(rr)         ((rr)->flags & DNS_RR_FLAG_TRUNCATED)
177 
178  /*
179   * dns_strerror.c
180   */
181 extern const char *dns_strerror(unsigned);
182 
183  /*
184   * dns_strtype.c
185   */
186 extern const char *dns_strtype(unsigned);
187 extern unsigned dns_type(const char *);
188 
189  /*
190   * dns_strrecord.c
191   */
192 extern char *dns_strrecord(VSTRING *, DNS_RR *);
193 
194  /*
195   * dns_rr.c
196   */
197 #define DNS_RR_NOPREF         (0)
198 #define DNS_RR_NOWEIGHT       (0)
199 #define DNS_RR_NOPORT         (0)
200 
201 #define dns_rr_create_noport(qname, rname, type, class, ttl, pref, data, \
202                                         data_len) \
203           dns_rr_create((qname), (rname), (type), (class), (ttl), \
204           (pref), DNS_RR_NOWEIGHT, DNS_RR_NOPORT, (data), (data_len))
205 
206 #define dns_rr_create_nopref(qname, rname, type, class, ttl, data, data_len) \
207           dns_rr_create_noport((qname), (rname), (type), (class), (ttl), \
208           DNS_RR_NOPREF, (data), (data_len))
209 
210 extern DNS_RR *dns_rr_create(const char *, const char *,
211                                            ushort, ushort,
212                                            unsigned, unsigned,
213                                            unsigned, unsigned,
214                                            const char *, size_t);
215 extern void dns_rr_free(DNS_RR *);
216 extern DNS_RR *dns_rr_copy(DNS_RR *);
217 extern DNS_RR *dns_rr_append(DNS_RR *, DNS_RR *);
218 extern DNS_RR *dns_rr_sort(DNS_RR *, int (*) (DNS_RR *, DNS_RR *));
219 extern DNS_RR *dns_srv_rr_sort(DNS_RR *);
220 extern int dns_rr_compare_pref_ipv6(DNS_RR *, DNS_RR *);
221 extern int dns_rr_compare_pref_ipv4(DNS_RR *, DNS_RR *);
222 extern int dns_rr_compare_pref_any(DNS_RR *, DNS_RR *);
223 extern int dns_rr_compare_pref(DNS_RR *, DNS_RR *);
224 extern DNS_RR *dns_rr_shuffle(DNS_RR *);
225 extern DNS_RR *dns_rr_remove(DNS_RR *, DNS_RR *);
226 extern DNS_RR *dns_rr_detach(DNS_RR *, DNS_RR *);
227 extern int var_dns_rr_list_limit;
228 
229  /*
230   * dns_rr_to_pa.c
231   */
232 extern const char *dns_rr_to_pa(DNS_RR *, MAI_HOSTADDR_STR *);
233 
234  /*
235   * dns_sa_to_rr.c
236   */
237 extern DNS_RR *dns_sa_to_rr(const char *, unsigned, struct sockaddr *);
238 
239  /*
240   * dns_rr_to_sa.c
241   */
242 extern int dns_rr_to_sa(DNS_RR *, unsigned, struct sockaddr *, SOCKADDR_SIZE *);
243 
244  /*
245   * dns_rr_eq_sa.c
246   */
247 extern int dns_rr_eq_sa(DNS_RR *, struct sockaddr *);
248 
249 #ifdef HAS_IPV6
250 #define DNS_RR_EQ_SA(rr, sa) \
251     ((SOCK_ADDR_IN_FAMILY(sa) == AF_INET && (rr)->type == T_A \
252      && SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR((rr)->data).s_addr) \
253     || (SOCK_ADDR_IN_FAMILY(sa) == AF_INET6 && (rr)->type == T_AAAA \
254           && memcmp((char *) &(SOCK_ADDR_IN6_ADDR(sa)), \
255                       (rr)->data, (rr)->data_len) == 0))
256 #else
257 #define DNS_RR_EQ_SA(rr, sa) \
258     (SOCK_ADDR_IN_FAMILY(sa) == AF_INET && (rr)->type == T_A \
259      && SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR((rr)->data).s_addr)
260 #endif
261 
262  /*
263   * dns_lookup.c
264   */
265 extern int dns_lookup_x(const char *, unsigned, unsigned, DNS_RR **,
266                                       VSTRING *, VSTRING *, int *, unsigned);
267 extern int dns_lookup_rl(const char *, unsigned, DNS_RR **, VSTRING *,
268                                        VSTRING *, int *, int,...);
269 extern int dns_lookup_rv(const char *, unsigned, DNS_RR **, VSTRING *,
270                                        VSTRING *, int *, int, unsigned *);
271 extern int dns_get_h_errno(void);
272 
273 #define dns_lookup(name, type, rflags, list, fqdn, why) \
274     dns_lookup_x((name), (type), (rflags), (list), (fqdn), (why), (int *) 0, \
275           (unsigned) 0)
276 #define dns_lookup_r(name, type, rflags, list, fqdn, why, rcode) \
277     dns_lookup_x((name), (type), (rflags), (list), (fqdn), (why), (rcode), \
278           (unsigned) 0)
279 #define dns_lookup_l(name, rflags, list, fqdn, why, lflags, ...) \
280     dns_lookup_rl((name), (rflags), (list), (fqdn), (why), (int *) 0, \
281           (lflags), __VA_ARGS__)
282 #define dns_lookup_v(name, rflags, list, fqdn, why, lflags, ltype) \
283     dns_lookup_rv((name), (rflags), (list), (fqdn), (why), (int *) 0, \
284           (lflags), (ltype))
285 
286  /*
287   * The dns_lookup() rflag that requests DNSSEC validation.
288   */
289 #define DNS_WANT_DNSSEC_VALIDATION(rflags)      ((rflags) & RES_USE_DNSSEC)
290 
291  /*
292   * lflags.
293   */
294 #define DNS_REQ_FLAG_STOP_OK  (1<<0)
295 #define DNS_REQ_FLAG_STOP_INVAL         (1<<1)
296 #define DNS_REQ_FLAG_STOP_NULLMX (1<<2)
297 #define DNS_REQ_FLAG_STOP_MX_POLICY (1<<3)
298 #define DNS_REQ_FLAG_NCACHE_TTL         (1<<4)
299 #define DNS_REQ_FLAG_NONE     (0)
300 
301  /*
302   * Status codes. Failures must have negative codes so they will not collide
303   * with valid counts of answer records etc.
304   *
305   * When a function queries multiple record types for one name, it issues one
306   * query for each query record type. Each query returns a (status, rcode,
307   * text). Only one of these (status, rcode, text) will be returned to the
308   * caller. The selection is based on the status code precedence.
309   *
310   * - Return DNS_OK (and the corresponding rcode) as long as any query returned
311   * DNS_OK. If this is changed, then code needs to be added to prevent memory
312   * leaks.
313   *
314   * - Return DNS_RETRY (and the corresponding rcode and text) instead of any
315   * hard negative result.
316   *
317   * - Return DNS_NOTFOUND (and the corresponding rcode and text) only when all
318   * queries returned DNS_NOTFOUND.
319   *
320   * DNS_POLICY ranks higher than DNS_RETRY because there was a DNS_OK result,
321   * but the reply filter dropped it. This is a very soft error.
322   *
323   * Below is the precedence order. The order between DNS_RETRY and DNS_NOTFOUND
324   * is arbitrary.
325   */
326 #define DNS_RECURSE (-8)                /* internal only: recursion needed */
327 #define DNS_NOTFOUND          (-7)                /* query ok, data not found */
328 #define DNS_NULLSRV (-6)                /* query ok, service unavailable */
329 #define DNS_NULLMX  (-5)                /* query ok, service unavailable */
330 #define DNS_FAIL    (-4)                /* query failed, don't retry */
331 #define DNS_INVAL   (-3)                /* query ok, malformed reply */
332 #define DNS_RETRY   (-2)                /* query failed, try again */
333 #define DNS_POLICY  (-1)                /* query ok, all records dropped */
334 #define DNS_OK                0                   /* query succeeded */
335 
336  /*
337   * How long can a DNS name or single text value be?
338   */
339 #define DNS_NAME_LEN          1024
340 
341  /*
342   * dns_rr_filter.c.
343   */
344 extern void dns_rr_filter_compile(const char *, const char *);
345 
346 #ifdef LIBDNS_INTERNAL
347 #include <maps.h>
348 extern MAPS *dns_rr_filter_maps;
349 extern int dns_rr_filter_execute(DNS_RR **);
350 
351 #endif
352 
353  /*
354   * dns_str_resflags.c
355   */
356 const char *dns_str_resflags(unsigned long);
357 
358  /*
359   * dns_sec.c.
360   */
361 #define DNS_SEC_FLAG_AVAILABLE          (1<<0)    /* got some DNSSEC validated reply */
362 #define DNS_SEC_FLAG_DONT_PROBE         (1<<1)    /* probe already sent, or disabled */
363 
364 #define DNS_SEC_STATS_SET(flags) (dns_sec_stats |= (flags))
365 #define DNS_SEC_STATS_TEST(flags) (dns_sec_stats & (flags))
366 
367 extern int dns_sec_stats;               /* See DNS_SEC_FLAG_XXX above */
368 extern void dns_sec_probe(int);
369 
370 /* LICENSE
371 /* .ad
372 /* .fi
373 /*        The Secure Mailer license must be distributed with this software.
374 /* AUTHOR(S)
375 /*        Wietse Venema
376 /*        IBM T.J. Watson Research
377 /*        P.O. Box 704
378 /*        Yorktown Heights, NY 10598, USA
379 /*
380 /*        Wietse Venema
381 /*        Google, Inc.
382 /*        111 8th Avenue
383 /*        New York, NY 10011, USA
384 /*--*/
385 
386 #endif
387