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