/* * dns.h -- DNS definitions. * * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. * * See LICENSE for the license. * */ #ifndef DNS_H #define DNS_H struct rr; struct buffer; struct domain; struct domain_table; struct query; enum rr_section { QUESTION_SECTION, ANSWER_SECTION, AUTHORITY_SECTION, /* * Use a split authority section to ensure that optional * NS RRsets in the response can be omitted. */ OPTIONAL_AUTHORITY_SECTION, ADDITIONAL_SECTION, /* * Use a split additional section to ensure A records appear * before any AAAA records (this is recommended practice to * avoid truncating the additional section for IPv4 clients * that do not specify EDNS0), and AAAA records before other * types of additional records (such as X25 and ISDN). * Encode_answer sets the ARCOUNT field of the response packet * correctly. */ ADDITIONAL_A_SECTION = ADDITIONAL_SECTION, ADDITIONAL_AAAA_SECTION, ADDITIONAL_OTHER_SECTION, RR_SECTION_COUNT }; typedef enum rr_section rr_section_type; /* Possible OPCODE values */ #define OPCODE_QUERY 0 /* a standard query (QUERY) */ #define OPCODE_IQUERY 1 /* an inverse query (IQUERY) */ #define OPCODE_STATUS 2 /* a server status request (STATUS) */ #define OPCODE_NOTIFY 4 /* NOTIFY */ #define OPCODE_UPDATE 5 /* Dynamic update */ /* Possible RCODE values */ #define RCODE_OK 0 /* No error condition */ #define RCODE_FORMAT 1 /* Format error */ #define RCODE_SERVFAIL 2 /* Server failure */ #define RCODE_NXDOMAIN 3 /* Name Error */ #define RCODE_IMPL 4 /* Not implemented */ #define RCODE_REFUSE 5 /* Refused */ #define RCODE_YXDOMAIN 6 /* name should not exist */ #define RCODE_YXRRSET 7 /* rrset should not exist */ #define RCODE_NXRRSET 8 /* rrset does not exist */ #define RCODE_NOTAUTH 9 /* server not authoritative */ #define RCODE_NOTZONE 10 /* name not inside zone */ /* Standardized NSD return code. Partially maps to DNS RCODE values. */ enum nsd_rc { /* Discard the client request. */ NSD_RC_DISCARD = -1, /* OK, continue normal processing. */ NSD_RC_OK = RCODE_OK, /* Return the appropriate error code to the client. */ NSD_RC_FORMAT = RCODE_FORMAT, NSD_RC_SERVFAIL = RCODE_SERVFAIL, NSD_RC_NXDOMAIN = RCODE_NXDOMAIN, NSD_RC_IMPL = RCODE_IMPL, NSD_RC_REFUSE = RCODE_REFUSE, NSD_RC_NOTAUTH = RCODE_NOTAUTH }; typedef enum nsd_rc nsd_rc_type; /* RFC1035 */ #define CLASS_IN 1 /* Class IN */ #define CLASS_CS 2 /* Class CS */ #define CLASS_CH 3 /* Class CHAOS */ #define CLASS_HS 4 /* Class HS */ #define CLASS_NONE 254 /* Class NONE rfc2136 */ #define CLASS_ANY 255 /* Class ANY */ #define TYPE_A 1 /* a host address */ #define TYPE_NS 2 /* an authoritative name server */ #define TYPE_MD 3 /* a mail destination (Obsolete - use MX) */ #define TYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ #define TYPE_CNAME 5 /* the canonical name for an alias */ #define TYPE_SOA 6 /* marks the start of a zone of authority */ #define TYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ #define TYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ #define TYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ #define TYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ #define TYPE_WKS 11 /* a well known service description */ #define TYPE_PTR 12 /* a domain name pointer */ #define TYPE_HINFO 13 /* host information */ #define TYPE_MINFO 14 /* mailbox or mail list information */ #define TYPE_MX 15 /* mail exchange */ #define TYPE_TXT 16 /* text strings */ #define TYPE_RP 17 /* RFC1183 */ #define TYPE_AFSDB 18 /* RFC1183 */ #define TYPE_X25 19 /* RFC1183 */ #define TYPE_ISDN 20 /* RFC1183 */ #define TYPE_RT 21 /* RFC1183 */ #define TYPE_NSAP 22 /* RFC1706 (deprecated by RFC9121) */ #define TYPE_NSAP_PTR 23 /* RFC1348 (deprecated by RFC9121) */ #define TYPE_SIG 24 /* 2535typecode */ #define TYPE_KEY 25 /* 2535typecode */ #define TYPE_PX 26 /* RFC2163 */ #define TYPE_GPOS 27 /* RFC1712 */ #define TYPE_AAAA 28 /* ipv6 address */ #define TYPE_LOC 29 /* LOC record RFC1876 */ #define TYPE_NXT 30 /* 2535typecode */ #define TYPE_EID 31 /* draft-ietf-nimrod-dns-01 */ #define TYPE_NIMLOC 32 /* draft-ietf-nimrod-dns-01 */ #define TYPE_SRV 33 /* SRV record RFC2782 */ #define TYPE_ATMA 34 /* ATM Address */ #define TYPE_NAPTR 35 /* RFC2915 */ #define TYPE_KX 36 /* RFC2230 Key Exchange Delegation Record */ #define TYPE_CERT 37 /* RFC2538 */ #define TYPE_A6 38 /* RFC2874 */ #define TYPE_DNAME 39 /* RFC2672 */ #define TYPE_SINK 40 /* draft-eastlake-kitchen-sink */ #define TYPE_OPT 41 /* Pseudo OPT record... */ #define TYPE_APL 42 /* RFC3123 */ #define TYPE_DS 43 /* RFC 4033, 4034, and 4035 */ #define TYPE_SSHFP 44 /* SSH Key Fingerprint */ #define TYPE_IPSECKEY 45 /* public key for ipsec use. RFC 4025 */ #define TYPE_RRSIG 46 /* RFC 4033, 4034, and 4035 */ #define TYPE_NSEC 47 /* RFC 4033, 4034, and 4035 */ #define TYPE_DNSKEY 48 /* RFC 4033, 4034, and 4035 */ #define TYPE_DHCID 49 /* RFC4701 DHCP information */ #define TYPE_NSEC3 50 /* NSEC3, secure denial, prevents zonewalking */ #define TYPE_NSEC3PARAM 51 /* NSEC3PARAM at zone apex nsec3 parameters */ #define TYPE_TLSA 52 /* RFC 6698 */ #define TYPE_SMIMEA 53 /* RFC 8162 */ #define TYPE_HIP 55 /* RFC 8005 */ #define TYPE_NINFO 56 /* NINFO/ninfo-completed-template */ #define TYPE_RKEY 57 /* RKEY/rkey-completed-template */ #define TYPE_TALINK 58 /* draft-ietf-dnsop-dnssec-trust-history */ #define TYPE_CDS 59 /* RFC 7344 */ #define TYPE_CDNSKEY 60 /* RFC 7344 */ #define TYPE_OPENPGPKEY 61 /* RFC 7929 */ #define TYPE_CSYNC 62 /* RFC 7477 */ #define TYPE_ZONEMD 63 /* RFC 8976 */ #define TYPE_SVCB 64 /* RFC 9460 */ #define TYPE_HTTPS 65 /* RFC 9460 */ #define TYPE_DSYNC 66 /* draft-ietf-dnsop-generalized-notify */ #define TYPE_SPF 99 /* RFC 4408 */ #define TYPE_NID 104 /* RFC 6742 */ #define TYPE_L32 105 /* RFC 6742 */ #define TYPE_L64 106 /* RFC 6742 */ #define TYPE_LP 107 /* RFC 6742 */ #define TYPE_EUI48 108 /* RFC 7043 */ #define TYPE_EUI64 109 /* RFC 7043 */ #define TYPE_NXNAME 128 /* draft-ietf-dnsop-compact-denial-of-existence-04 */ #define TYPE_TSIG 250 /* RFC 2845 */ #define TYPE_IXFR 251 /* RFC 1995 */ #define TYPE_AXFR 252 /* RFC 1035, RFC 5936 */ #define TYPE_MAILB 253 /* A request for mailbox-related records (MB, MG or MR) [RFC 1035] */ #define TYPE_MAILA 254 /* A request for mail agent RRs (Obsolete - see MX) [RFC 1035] */ #define TYPE_ANY 255 /* any type (wildcard) [RFC 1035, RFC 6895] */ #define TYPE_URI 256 /* RFC 7553 */ #define TYPE_CAA 257 /* RFC 6844 */ #define TYPE_AVC 258 /* AVC/avc-completed-template */ #define TYPE_DOA 259 /* draft-durand-doa-over-dns */ #define TYPE_AMTRELAY 260 /* RFC 8777 */ #define TYPE_RESINFO 261 /* RFC 9606 */ #define TYPE_WALLET 262 /* WALLET/wallet-completed-template */ #define TYPE_CLA 263 /* CLA/cla-completed-template */ #define TYPE_IPN 264 /* IPN/ipn-completed-template draft-johnson-dns-ipn-cla-07 */ #define TYPE_TA 32768 /* http://www.watson.org/~weiler/INI1999-19.pdf */ #define TYPE_DLV 32769 /* RFC 4431 */ #define SVCB_KEY_MANDATORY 0 #define SVCB_KEY_ALPN 1 #define SVCB_KEY_NO_DEFAULT_ALPN 2 #define SVCB_KEY_PORT 3 #define SVCB_KEY_IPV4HINT 4 #define SVCB_KEY_ECH 5 #define SVCB_KEY_IPV6HINT 6 #define SVCB_KEY_DOHPATH 7 #define SVCB_KEY_OHTTP 8 #define SVCB_KEY_TLS_SUPPORTED_GROUPS 9 #define MAXLABELLEN 63 #define MAXDOMAINLEN 255 #define MAX_RDLENGTH 65535 /* Maximum size of a single RR. */ #define MAX_RR_SIZE \ (MAXDOMAINLEN + sizeof(uint32_t) + 4*sizeof(uint16_t) + MAX_RDLENGTH) #define IP4ADDRLEN (32/8) #define IP6ADDRLEN (128/8) #define EUI48ADDRLEN (48/8) #define EUI64ADDRLEN (64/8) #define NSEC3_HASH_LEN 20 /* * The following RDATA values are used in nsd_rdata_descriptor.length to * indicate a specialized value. They are negative, the normal lengths * are 0..65535 and length is int32_t. */ /* The rdata is a compressed domain name. In namedb it is a reference * with a pointer to struct domain. On the wire, the name can be a * compressed name. The pointer is stored in line and is likely unaligned. */ #define RDATA_COMPRESSED_DNAME -1 /* The rdata is an uncompressed domain name. In namedb it is a reference * with a pointer to struct domain. The pointer is stored in line and is * likely unaligned. */ #define RDATA_UNCOMPRESSED_DNAME -2 /* The rdata is a literal domain name. It is not a reference to struct * domain, and stored as uncompressed wireformat octets. */ #define RDATA_LITERAL_DNAME -3 /* The rdata is a string. It starts with a uint8_t length byte. */ #define RDATA_STRING -4 /* The rdata is binary. It starts with a uint8_t length byte. */ #define RDATA_BINARY -5 /* The rdata is of type IPSECGATEWAY because of its encoding elsewhere in * the RR. */ #define RDATA_IPSECGATEWAY -6 /* The rdata is the remainder of the record, to the end of the bytes, possibly * zero bytes. The length of the field is determined by the rdata length. */ #define RDATA_REMAINDER -7 /* The rdata is of type AMTRELAYRELAY because of its encoding elsewhere in * the RR. */ #define RDATA_AMTRELAY_RELAY -8 /* * Function signature to determine length of the rdata field. * @param rdlength: length of the input rdata. * @param rdata: input bytes with rdata of the RR. * @param offset: current byte position in rdata. * offset is required for the ipsecgateway where we need to read * a couple bytes back * @param domain: this value can be returned as NULL, in which case the * function return value is a length in bytes in wireformat. * If this value is returned nonNULL, it is the special reference * object that needs different treatment. The function return value * is the length that needs to be skipped in rdata to get past the * field, that is a reference when that is a pointer. * For other types of objects an additional function argument could be * added, and then handling in the caller. * @return length in bytes. Or -1 on failure, like rdata length too short. */ typedef int32_t(*nsd_rdata_field_length_type)( uint16_t rdlength, const uint8_t *rdata, uint16_t offset, struct domain** domain); typedef struct nsd_rdata_descriptor nsd_rdata_descriptor_type; /* * Descriptor table. For DNS RRTypes has information on the resource record * type. the descriptor table shouldn't be used for validation. * the read function will take care of that. it's used for * implementing copy functions that are very specific, but where * the data has already been checked for validity. */ struct nsd_rdata_descriptor { /* Field name of the rdata, like 'primary server'. */ const char *name; /* If the field is optional. When the field is not present, eg. no * bytes of rdata, and it is optional, this is fine and the rdata * is shorter. Also no following rdatas after it. Non optional * rdatas must be present. */ int is_optional; /* The length, in bytes, of the rdata field. Can be set to * a specialized value, like RDATA_COMPRESSED_DNAME, * RDATA_STRING, ..., if there is a length function, that is used. * That is for any type where the length depends on a value in * the rdata itself. */ int32_t length; /* Determine size of rdata field. Returns the size of uncompressed * rdata on the wire, or -1 on failure, like when it is malformed. * So for references this is a different number. Used for ipseckey * gateway, because the type depends on earlier data. Also amtrelay * relay. This function takes the in-memory rdata representation. * If the field has a special object, return -1 on failure or the * length of the object in the rdata, with domain ptr returned to * the special object. */ nsd_rdata_field_length_type calculate_length; /* Determine size of rdata field. Like calculate_length, but this * function takes uncompressed wireformat in the rdata that is passed. */ nsd_rdata_field_length_type calculate_length_uncompressed_wire; }; typedef struct nsd_type_descriptor nsd_type_descriptor_type; struct nsd_type_descriptor; /* The rdata is malformed. The wireformat is not correct. * NSD cannot store a wireformat with a malformed domain name, when that * name needs to become a reference to struct domain. */ #define MALFORMED -1 /* The rdata is not read, it is truncated, some was copied, but then * an error occurred, like memory allocation failure. */ #define TRUNCATED -2 /* * Function signature to read rdata. From a packet into memory. * @param domains: the domain table. * @param rdlength: the length of the rdata in the packet. * @param packet: the packet. * @param rr: an RR is returned. * @return the number of bytes that are read from the packet. Or negative * for an error, like MALFORMED, TRUNCATED. */ typedef int32_t(*nsd_read_rdata_type)( struct domain_table *domains, uint16_t rdlength, struct buffer *packet, struct rr **rr); /* * Function signature to write rdata. From memory to an answer. * @param query: the query that is answered. * @param rr: rr to add to the output, in query.packet. It prints the rdata * wireformat to the packet, compressed if needed, not including the * rdlength before the rdata. */ typedef void(*nsd_write_rdata_type)( struct query *query, const struct rr *rr); /* * Function signature to print rdata. The string is in the buffer. * The printed string starts with the rdata text. It does not have a newline * at end. No space is put before it. * @param output: buffer with string on return. The position is moved. * @param rr: the record to print the rdata for. * @return false on failure. The wireformat can not be printed in the * nice output format. */ typedef int(*nsd_print_rdata_type)( struct buffer *output, const struct rr *rr); /* * Descriptor for a DNS resource record type. * There are conversion routines per type, for wire-to-internal, * internal-to-wire, and internal-to-text. To stop an explosion in code, * there is an rdata field descriptor array to convert between more formats. * For internal to compressed wire format we implement a specialized routine so * that answering of queries is as optimal as can be. * Other formats are conversion from uncompressed wire format to compressed * wire format. For conversion from uncompressed or compressed wire format * to internal the same import routines can be used, by using a packet buffer * and dname_make_from_packet. */ struct nsd_type_descriptor { /* The RRType number */ uint16_t type; /* Mnemonic. */ const char *name; /* Whether internal RDATA contains direct pointers. * This means the namedb memory contains an in line pointer to * struct domain for domain names. */ int has_references; /* Whether RDATA contains compressible names. The output can be * compressed on the packet. If true, also has_references is true, * for the packet encode routine, that uses the references. */ int is_compressible; /* The type has domain names, like literal dnames in the format. */ int has_dnames; /* Read function that copies rdata for this type to struct rr. */ nsd_read_rdata_type read_rdata; /* Write function, that copies rdata from struct rr to packet. */ nsd_write_rdata_type write_rdata; /* Print function, that writes the struct rr to string. */ nsd_print_rdata_type print_rdata; /* Description of the rdata fields. Used by functions that need * to iterate over the fields. There are binary fields and * references, and wireformat domain names. */ struct { /* Length of the fields array. */ size_t length; /* The rdata field descriptors. */ const nsd_rdata_descriptor_type *fields; } rdata; }; /* The length of the RRTYPE descriptors arrary */ #define RRTYPE_DESCRIPTORS_LENGTH (TYPE_IPN + 2) /* * Indexed by type. The special type "0" can be used to get a * descriptor for unknown types (with one binary rdata). */ static inline const nsd_type_descriptor_type *nsd_type_descriptor( uint16_t rrtype); const char *rrtype_to_string(uint16_t rrtype); /* * Lookup the type in the ztypes lookup table. If not found, check if * the type uses the "TYPExxx" notation for unknown types. * * Return 0 if no type matches. */ uint16_t rrtype_from_string(const char *name); const char *rrclass_to_string(uint16_t rrclass); uint16_t rrclass_from_string(const char *name); /* The type descriptors array of length RRTYPE_DESCRIPTORS_LENGTH. */ extern const nsd_type_descriptor_type type_descriptors[]; static inline const nsd_type_descriptor_type * nsd_type_descriptor(uint16_t rrtype) { if (rrtype <= TYPE_IPN) return &type_descriptors[rrtype]; if (rrtype == TYPE_TA) return &type_descriptors[TYPE_IPN + 1]; if (rrtype == TYPE_DLV) return &type_descriptors[TYPE_IPN + 2]; return &type_descriptors[0]; } #endif /* DNS_H */