Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: dns.h,v 1.8 2026/05/09 18:49:15 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	MAXDNAME	/* From <arpa/nameser.h */
    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