1 /*	$NetBSD: dns.h,v 1.5 2022/10/08 16:12:45 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: http://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 only */
164     struct DNS_RR *next;		/* linkage */
165     size_t  data_len;			/* actual data size */
166     char    data[1];			/* actually a bunch of data */
167 } DNS_RR;
168 
169  /*
170   * dns_strerror.c
171   */
172 extern const char *dns_strerror(unsigned);
173 
174  /*
175   * dns_strtype.c
176   */
177 extern const char *dns_strtype(unsigned);
178 extern unsigned dns_type(const char *);
179 
180  /*
181   * dns_strrecord.c
182   */
183 extern char *dns_strrecord(VSTRING *, DNS_RR *);
184 
185  /*
186   * dns_rr.c
187   */
188 extern DNS_RR *dns_rr_create(const char *, const char *,
189 			             ushort, ushort,
190 			             unsigned, unsigned,
191 			             const char *, size_t);
192 extern void dns_rr_free(DNS_RR *);
193 extern DNS_RR *dns_rr_copy(DNS_RR *);
194 extern DNS_RR *dns_rr_append(DNS_RR *, DNS_RR *);
195 extern DNS_RR *dns_rr_sort(DNS_RR *, int (*) (DNS_RR *, DNS_RR *));
196 extern int dns_rr_compare_pref_ipv6(DNS_RR *, DNS_RR *);
197 extern int dns_rr_compare_pref_ipv4(DNS_RR *, DNS_RR *);
198 extern int dns_rr_compare_pref_any(DNS_RR *, DNS_RR *);
199 extern int dns_rr_compare_pref(DNS_RR *, DNS_RR *);
200 extern DNS_RR *dns_rr_shuffle(DNS_RR *);
201 extern DNS_RR *dns_rr_remove(DNS_RR *, DNS_RR *);
202 
203  /*
204   * dns_rr_to_pa.c
205   */
206 extern const char *dns_rr_to_pa(DNS_RR *, MAI_HOSTADDR_STR *);
207 
208  /*
209   * dns_sa_to_rr.c
210   */
211 extern DNS_RR *dns_sa_to_rr(const char *, unsigned, struct sockaddr *);
212 
213  /*
214   * dns_rr_to_sa.c
215   */
216 extern int dns_rr_to_sa(DNS_RR *, unsigned, struct sockaddr *, SOCKADDR_SIZE *);
217 
218  /*
219   * dns_rr_eq_sa.c
220   */
221 extern int dns_rr_eq_sa(DNS_RR *, struct sockaddr *);
222 
223 #ifdef HAS_IPV6
224 #define DNS_RR_EQ_SA(rr, sa) \
225     ((SOCK_ADDR_IN_FAMILY(sa) == AF_INET && (rr)->type == T_A \
226      && SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR((rr)->data).s_addr) \
227     || (SOCK_ADDR_IN_FAMILY(sa) == AF_INET6 && (rr)->type == T_AAAA \
228 	&& memcmp((char *) &(SOCK_ADDR_IN6_ADDR(sa)), \
229 		  (rr)->data, (rr)->data_len) == 0))
230 #else
231 #define DNS_RR_EQ_SA(rr, sa) \
232     (SOCK_ADDR_IN_FAMILY(sa) == AF_INET && (rr)->type == T_A \
233      && SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR((rr)->data).s_addr)
234 #endif
235 
236  /*
237   * dns_lookup.c
238   */
239 extern int dns_lookup_x(const char *, unsigned, unsigned, DNS_RR **,
240 			        VSTRING *, VSTRING *, int *, unsigned);
241 extern int dns_lookup_rl(const char *, unsigned, DNS_RR **, VSTRING *,
242 			         VSTRING *, int *, int,...);
243 extern int dns_lookup_rv(const char *, unsigned, DNS_RR **, VSTRING *,
244 			         VSTRING *, int *, int, unsigned *);
245 extern int dns_get_h_errno(void);
246 
247 #define dns_lookup(name, type, rflags, list, fqdn, why) \
248     dns_lookup_x((name), (type), (rflags), (list), (fqdn), (why), (int *) 0, \
249 	(unsigned) 0)
250 #define dns_lookup_r(name, type, rflags, list, fqdn, why, rcode) \
251     dns_lookup_x((name), (type), (rflags), (list), (fqdn), (why), (rcode), \
252 	(unsigned) 0)
253 #define dns_lookup_l(name, rflags, list, fqdn, why, lflags, ...) \
254     dns_lookup_rl((name), (rflags), (list), (fqdn), (why), (int *) 0, \
255 	(lflags), __VA_ARGS__)
256 #define dns_lookup_v(name, rflags, list, fqdn, why, lflags, ltype) \
257     dns_lookup_rv((name), (rflags), (list), (fqdn), (why), (int *) 0, \
258 	(lflags), (ltype))
259 
260  /*
261   * The dns_lookup() rflag that requests DNSSEC validation.
262   */
263 #define DNS_WANT_DNSSEC_VALIDATION(rflags)      ((rflags) & RES_USE_DNSSEC)
264 
265  /*
266   * lflags.
267   */
268 #define DNS_REQ_FLAG_STOP_OK	(1<<0)
269 #define DNS_REQ_FLAG_STOP_INVAL	(1<<1)
270 #define DNS_REQ_FLAG_STOP_NULLMX (1<<2)
271 #define DNS_REQ_FLAG_STOP_MX_POLICY (1<<3)
272 #define DNS_REQ_FLAG_NCACHE_TTL	(1<<4)
273 #define DNS_REQ_FLAG_NONE	(0)
274 
275  /*
276   * Status codes. Failures must have negative codes so they will not collide
277   * with valid counts of answer records etc.
278   *
279   * When a function queries multiple record types for one name, it issues one
280   * query for each query record type. Each query returns a (status, rcode,
281   * text). Only one of these (status, rcode, text) will be returned to the
282   * caller. The selection is based on the status code precedence.
283   *
284   * - Return DNS_OK (and the corresponding rcode) as long as any query returned
285   * DNS_OK. If this is changed, then code needs to be added to prevent memory
286   * leaks.
287   *
288   * - Return DNS_RETRY (and the corresponding rcode and text) instead of any
289   * hard negative result.
290   *
291   * - Return DNS_NOTFOUND (and the corresponding rcode and text) only when all
292   * queries returned DNS_NOTFOUND.
293   *
294   * DNS_POLICY ranks higher than DNS_RETRY because there was a DNS_OK result,
295   * but the reply filter dropped it. This is a very soft error.
296   *
297   * Below is the precedence order. The order between DNS_RETRY and DNS_NOTFOUND
298   * is arbitrary.
299   */
300 #define DNS_RECURSE	(-7)		/* internal only: recursion needed */
301 #define DNS_NOTFOUND	(-6)		/* query ok, data not found */
302 #define DNS_NULLMX	(-5)		/* query ok, service unavailable */
303 #define DNS_FAIL	(-4)		/* query failed, don't retry */
304 #define DNS_INVAL	(-3)		/* query ok, malformed reply */
305 #define DNS_RETRY	(-2)		/* query failed, try again */
306 #define DNS_POLICY	(-1)		/* query ok, all records dropped */
307 #define DNS_OK		0		/* query succeeded */
308 
309  /*
310   * How long can a DNS name or single text value be?
311   */
312 #define DNS_NAME_LEN	1024
313 
314  /*
315   * dns_rr_filter.c.
316   */
317 extern void dns_rr_filter_compile(const char *, const char *);
318 
319 #ifdef LIBDNS_INTERNAL
320 #include <maps.h>
321 extern MAPS *dns_rr_filter_maps;
322 extern int dns_rr_filter_execute(DNS_RR **);
323 
324 #endif
325 
326  /*
327   * dns_str_resflags.c
328   */
329 const char *dns_str_resflags(unsigned long);
330 
331  /*
332   * dns_sec.c.
333   */
334 #define DNS_SEC_FLAG_AVAILABLE	(1<<0)	/* got some DNSSEC validated reply */
335 #define DNS_SEC_FLAG_DONT_PROBE	(1<<1)	/* probe already sent, or disabled */
336 
337 #define DNS_SEC_STATS_SET(flags) (dns_sec_stats |= (flags))
338 #define DNS_SEC_STATS_TEST(flags) (dns_sec_stats & (flags))
339 
340 extern int dns_sec_stats;		/* See DNS_SEC_FLAG_XXX above */
341 extern void dns_sec_probe(int);
342 
343 /* LICENSE
344 /* .ad
345 /* .fi
346 /*	The Secure Mailer license must be distributed with this software.
347 /* AUTHOR(S)
348 /*	Wietse Venema
349 /*	IBM T.J. Watson Research
350 /*	P.O. Box 704
351 /*	Yorktown Heights, NY 10598, USA
352 /*
353 /*	Wietse Venema
354 /*	Google, Inc.
355 /*	111 8th Avenue
356 /*	New York, NY 10011, USA
357 /*--*/
358 
359 #endif
360