diff options
Diffstat (limited to 'src/dns/dns.h')
-rw-r--r-- | src/dns/dns.h | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/src/dns/dns.h b/src/dns/dns.h new file mode 100644 index 0000000..5f53dbc --- /dev/null +++ b/src/dns/dns.h @@ -0,0 +1,357 @@ +#ifndef _DNS_H_INCLUDED_ +#define _DNS_H_INCLUDED_ + +/*++ +/* NAME +/* dns 3h +/* SUMMARY +/* domain name service lookup +/* SYNOPSIS +/* #include <dns.h> +/* DESCRIPTION +/* .nf + + /* + * System library. + */ +#include <netinet/in.h> +#include <arpa/nameser.h> +#ifdef RESOLVE_H_NEEDS_STDIO_H +#include <stdio.h> +#endif +#ifdef RESOLVE_H_NEEDS_NAMESER8_COMPAT_H +#include <nameser8_compat.h> +#endif +#ifdef RESOLVE_H_NEEDS_ARPA_NAMESER_COMPAT_H +#include <arpa/nameser_compat.h> +#endif +#include <resolv.h> + + /* + * Name server compatibility. These undocumented macros appear in the file + * <arpa/nameser.h>, but since they are undocumented we should not count on + * their presence, and so they are included here just in case. + */ +#ifndef GETSHORT + +#define GETSHORT(s, cp) { \ + unsigned char *t_cp = (u_char *)(cp); \ + (s) = ((unsigned)t_cp[0] << 8) \ + | ((unsigned)t_cp[1]) \ + ; \ + (cp) += 2; \ +} + +#define GETLONG(l, cp) { \ + unsigned char *t_cp = (u_char *)(cp); \ + (l) = ((unsigned)t_cp[0] << 24) \ + | ((unsigned)t_cp[1] << 16) \ + | ((unsigned)t_cp[2] << 8) \ + | ((unsigned)t_cp[3]) \ + ; \ + (cp) += 4; \ +} + +#endif + + /* + * Provide API compatibility for systems without res_nxxx() API. Also + * require calling dns_get_h_errno() instead of directly accessing the + * global h_errno variable. We should not count on that being updated. + */ +#if !defined(NO_RES_NCALLS) && defined(__RES) && (__RES >= 19991006) +#define USE_RES_NCALLS +#undef h_errno +#define h_errno use_dns_get_h_errno_instead_of_h_errno +#endif + +/* + * Disable DNSSEC at compile-time even if RES_USE_DNSSEC is available + */ +#ifdef NO_DNSSEC +#undef RES_USE_DNSSEC +#undef RES_TRUSTAD +#endif + + /* + * Compatibility with systems that lack RES_USE_DNSSEC and RES_USE_EDNS0 + */ +#ifndef RES_USE_DNSSEC +#define RES_USE_DNSSEC 0 +#endif +#ifndef RES_USE_EDNS0 +#define RES_USE_EDNS0 0 +#endif +#ifndef RES_TRUSTAD +#define RES_TRUSTAD 0 +#endif + + /*- + * TLSA: https://tools.ietf.org/html/rfc6698#section-7.1 + * RRSIG: http://tools.ietf.org/html/rfc4034#section-3 + * + * We don't request RRSIG, but we get it "for free" when we send the DO-bit. + */ +#ifndef T_TLSA +#define T_TLSA 52 +#endif +#ifndef T_RRSIG +#define T_RRSIG 46 /* Avoid unknown RR in logs */ +#endif +#ifndef T_DNAME +#define T_DNAME 39 /* [RFC6672] */ +#endif + + /* + * https://tools.ietf.org/html/rfc6698#section-7.2 + */ +#define DNS_TLSA_USAGE_CA_CONSTRAINT 0 +#define DNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT 1 +#define DNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION 2 +#define DNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE 3 + + /* + * https://tools.ietf.org/html/rfc6698#section-7.3 + */ +#define DNS_TLSA_SELECTOR_FULL_CERTIFICATE 0 +#define DNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO 1 + + /* + * https://tools.ietf.org/html/rfc6698#section-7.4 + */ +#define DNS_TLSA_MATCHING_TYPE_NO_HASH_USED 0 +#define DNS_TLSA_MATCHING_TYPE_SHA256 1 +#define DNS_TLSA_MATCHING_TYPE_SHA512 2 + + /* + * SunOS 4 needs this. + */ +#ifndef T_TXT +#define T_TXT 16 +#endif + + /* + * Utility library. + */ +#include <vstring.h> +#include <sock_addr.h> +#include <myaddrinfo.h> + + /* + * Structure for fixed resource record data. + */ +typedef struct DNS_FIXED { + unsigned short type; /* T_A, T_CNAME, etc. */ + unsigned short class; /* C_IN, etc. */ + unsigned int ttl; /* always */ + unsigned length; /* record length */ +} DNS_FIXED; + + /* + * Structure of a DNS resource record after expansion. The components are + * named after the things one can expect to find in a DNS resource record. + */ +typedef struct DNS_RR { + char *qname; /* query name, mystrdup()ed */ + char *rname; /* reply name, mystrdup()ed */ + unsigned short type; /* T_A, T_CNAME, etc. */ + unsigned short class; /* C_IN, etc. */ + unsigned int ttl; /* always */ + unsigned int dnssec_valid; /* DNSSEC validated */ + unsigned short pref; /* T_MX only */ + struct DNS_RR *next; /* linkage */ + size_t data_len; /* actual data size */ + char data[1]; /* actually a bunch of data */ +} DNS_RR; + + /* + * dns_strerror.c + */ +extern const char *dns_strerror(unsigned); + + /* + * dns_strtype.c + */ +extern const char *dns_strtype(unsigned); +extern unsigned dns_type(const char *); + + /* + * dns_strrecord.c + */ +extern char *dns_strrecord(VSTRING *, DNS_RR *); + + /* + * dns_rr.c + */ +extern DNS_RR *dns_rr_create(const char *, const char *, + ushort, ushort, + unsigned, unsigned, + const char *, size_t); +extern void dns_rr_free(DNS_RR *); +extern DNS_RR *dns_rr_copy(DNS_RR *); +extern DNS_RR *dns_rr_append(DNS_RR *, DNS_RR *); +extern DNS_RR *dns_rr_sort(DNS_RR *, int (*) (DNS_RR *, DNS_RR *)); +extern int dns_rr_compare_pref_ipv6(DNS_RR *, DNS_RR *); +extern int dns_rr_compare_pref_ipv4(DNS_RR *, DNS_RR *); +extern int dns_rr_compare_pref_any(DNS_RR *, DNS_RR *); +extern int dns_rr_compare_pref(DNS_RR *, DNS_RR *); +extern DNS_RR *dns_rr_shuffle(DNS_RR *); +extern DNS_RR *dns_rr_remove(DNS_RR *, DNS_RR *); + + /* + * dns_rr_to_pa.c + */ +extern const char *dns_rr_to_pa(DNS_RR *, MAI_HOSTADDR_STR *); + + /* + * dns_sa_to_rr.c + */ +extern DNS_RR *dns_sa_to_rr(const char *, unsigned, struct sockaddr *); + + /* + * dns_rr_to_sa.c + */ +extern int dns_rr_to_sa(DNS_RR *, unsigned, struct sockaddr *, SOCKADDR_SIZE *); + + /* + * dns_rr_eq_sa.c + */ +extern int dns_rr_eq_sa(DNS_RR *, struct sockaddr *); + +#ifdef HAS_IPV6 +#define DNS_RR_EQ_SA(rr, sa) \ + ((SOCK_ADDR_IN_FAMILY(sa) == AF_INET && (rr)->type == T_A \ + && SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR((rr)->data).s_addr) \ + || (SOCK_ADDR_IN_FAMILY(sa) == AF_INET6 && (rr)->type == T_AAAA \ + && memcmp((char *) &(SOCK_ADDR_IN6_ADDR(sa)), \ + (rr)->data, (rr)->data_len) == 0)) +#else +#define DNS_RR_EQ_SA(rr, sa) \ + (SOCK_ADDR_IN_FAMILY(sa) == AF_INET && (rr)->type == T_A \ + && SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR((rr)->data).s_addr) +#endif + + /* + * dns_lookup.c + */ +extern int dns_lookup_x(const char *, unsigned, unsigned, DNS_RR **, + VSTRING *, VSTRING *, int *, unsigned); +extern int dns_lookup_rl(const char *, unsigned, DNS_RR **, VSTRING *, + VSTRING *, int *, int,...); +extern int dns_lookup_rv(const char *, unsigned, DNS_RR **, VSTRING *, + VSTRING *, int *, int, unsigned *); +extern int dns_get_h_errno(void); + +#define dns_lookup(name, type, rflags, list, fqdn, why) \ + dns_lookup_x((name), (type), (rflags), (list), (fqdn), (why), (int *) 0, \ + (unsigned) 0) +#define dns_lookup_r(name, type, rflags, list, fqdn, why, rcode) \ + dns_lookup_x((name), (type), (rflags), (list), (fqdn), (why), (rcode), \ + (unsigned) 0) +#define dns_lookup_l(name, rflags, list, fqdn, why, lflags, ...) \ + dns_lookup_rl((name), (rflags), (list), (fqdn), (why), (int *) 0, \ + (lflags), __VA_ARGS__) +#define dns_lookup_v(name, rflags, list, fqdn, why, lflags, ltype) \ + dns_lookup_rv((name), (rflags), (list), (fqdn), (why), (int *) 0, \ + (lflags), (ltype)) + + /* + * The dns_lookup() rflag that requests DNSSEC validation. + */ +#define DNS_WANT_DNSSEC_VALIDATION(rflags) ((rflags) & RES_USE_DNSSEC) + + /* + * lflags. + */ +#define DNS_REQ_FLAG_STOP_OK (1<<0) +#define DNS_REQ_FLAG_STOP_INVAL (1<<1) +#define DNS_REQ_FLAG_STOP_NULLMX (1<<2) +#define DNS_REQ_FLAG_STOP_MX_POLICY (1<<3) +#define DNS_REQ_FLAG_NCACHE_TTL (1<<4) +#define DNS_REQ_FLAG_NONE (0) + + /* + * Status codes. Failures must have negative codes so they will not collide + * with valid counts of answer records etc. + * + * When a function queries multiple record types for one name, it issues one + * query for each query record type. Each query returns a (status, rcode, + * text). Only one of these (status, rcode, text) will be returned to the + * caller. The selection is based on the status code precedence. + * + * - Return DNS_OK (and the corresponding rcode) as long as any query returned + * DNS_OK. If this is changed, then code needs to be added to prevent memory + * leaks. + * + * - Return DNS_RETRY (and the corresponding rcode and text) instead of any + * hard negative result. + * + * - Return DNS_NOTFOUND (and the corresponding rcode and text) only when all + * queries returned DNS_NOTFOUND. + * + * DNS_POLICY ranks higher than DNS_RETRY because there was a DNS_OK result, + * but the reply filter dropped it. This is a very soft error. + * + * Below is the precedence order. The order between DNS_RETRY and DNS_NOTFOUND + * is arbitrary. + */ +#define DNS_RECURSE (-7) /* internal only: recursion needed */ +#define DNS_NOTFOUND (-6) /* query ok, data not found */ +#define DNS_NULLMX (-5) /* query ok, service unavailable */ +#define DNS_FAIL (-4) /* query failed, don't retry */ +#define DNS_INVAL (-3) /* query ok, malformed reply */ +#define DNS_RETRY (-2) /* query failed, try again */ +#define DNS_POLICY (-1) /* query ok, all records dropped */ +#define DNS_OK 0 /* query succeeded */ + + /* + * How long can a DNS name or single text value be? + */ +#define DNS_NAME_LEN 1024 + + /* + * dns_rr_filter.c. + */ +extern void dns_rr_filter_compile(const char *, const char *); + +#ifdef LIBDNS_INTERNAL +#include <maps.h> +extern MAPS *dns_rr_filter_maps; +extern int dns_rr_filter_execute(DNS_RR **); + +#endif + + /* + * dns_str_resflags.c + */ +const char *dns_str_resflags(unsigned long); + + /* + * dns_sec.c. + */ +#define DNS_SEC_FLAG_AVAILABLE (1<<0) /* got some DNSSEC validated reply */ +#define DNS_SEC_FLAG_DONT_PROBE (1<<1) /* probe already sent, or disabled */ + +#define DNS_SEC_STATS_SET(flags) (dns_sec_stats |= (flags)) +#define DNS_SEC_STATS_TEST(flags) (dns_sec_stats & (flags)) + +extern int dns_sec_stats; /* See DNS_SEC_FLAG_XXX above */ +extern void dns_sec_probe(int); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +#endif |