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