1*5afab0e5SDag-Erling Smørgrav /* 2*5afab0e5SDag-Erling Smørgrav * edns.h 3*5afab0e5SDag-Erling Smørgrav * 4*5afab0e5SDag-Erling Smørgrav * 5*5afab0e5SDag-Erling Smørgrav * a Net::DNS like library for C 6*5afab0e5SDag-Erling Smørgrav * 7*5afab0e5SDag-Erling Smørgrav * (c) NLnet Labs, 2004-2022 8*5afab0e5SDag-Erling Smørgrav * 9*5afab0e5SDag-Erling Smørgrav * See the file LICENSE for the license 10*5afab0e5SDag-Erling Smørgrav */ 11*5afab0e5SDag-Erling Smørgrav 12*5afab0e5SDag-Erling Smørgrav #ifndef LDNS_EDNS_H 13*5afab0e5SDag-Erling Smørgrav #define LDNS_EDNS_H 14*5afab0e5SDag-Erling Smørgrav 15*5afab0e5SDag-Erling Smørgrav #include <ldns/common.h> 16*5afab0e5SDag-Erling Smørgrav 17*5afab0e5SDag-Erling Smørgrav #ifdef __cplusplus 18*5afab0e5SDag-Erling Smørgrav extern "C" { 19*5afab0e5SDag-Erling Smørgrav #endif 20*5afab0e5SDag-Erling Smørgrav 21*5afab0e5SDag-Erling Smørgrav 22*5afab0e5SDag-Erling Smørgrav 23*5afab0e5SDag-Erling Smørgrav /** 24*5afab0e5SDag-Erling Smørgrav * EDNS option codes 25*5afab0e5SDag-Erling Smørgrav */ 26*5afab0e5SDag-Erling Smørgrav enum ldns_enum_edns_option 27*5afab0e5SDag-Erling Smørgrav { 28*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_LLQ = 1, /* RFC8764 */ 29*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_UL = 2, /* http://files.dns-sd.org/draft-sekar-dns-ul.txt */ 30*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_NSID = 3, /* RFC5001 */ 31*5afab0e5SDag-Erling Smørgrav /* 4 draft-cheshire-edns0-owner-option */ 32*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_DAU = 5, /* RFC6975 */ 33*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_DHU = 6, /* RFC6975 */ 34*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_N3U = 7, /* RFC6975 */ 35*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */ 36*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_EXPIRE = 9, /* RFC7314 */ 37*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_COOKIE = 10, /* RFC7873 */ 38*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_KEEPALIVE = 11, /* RFC7828*/ 39*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_PADDING = 12, /* RFC7830 */ 40*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_CHAIN = 13, /* RFC7901 */ 41*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_KEY_TAG = 14, /* RFC8145 */ 42*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_EDE = 15, /* RFC8914 */ 43*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_CLIENT_TAG = 16, /* draft-bellis-dnsop-edns-tags-01 */ 44*5afab0e5SDag-Erling Smørgrav LDNS_EDNS_SERVER_TAG = 17 /* draft-bellis-dnsop-edns-tags-01 */ 45*5afab0e5SDag-Erling Smørgrav }; 46*5afab0e5SDag-Erling Smørgrav typedef enum ldns_enum_edns_option ldns_edns_option_code; 47*5afab0e5SDag-Erling Smørgrav 48*5afab0e5SDag-Erling Smørgrav /** 49*5afab0e5SDag-Erling Smørgrav * Extended DNS Error (RFC 8914) codes 50*5afab0e5SDag-Erling Smørgrav */ 51*5afab0e5SDag-Erling Smørgrav enum ldns_edns_enum_ede_code 52*5afab0e5SDag-Erling Smørgrav { 53*5afab0e5SDag-Erling Smørgrav LDNS_EDE_OTHER = 0, 54*5afab0e5SDag-Erling Smørgrav LDNS_EDE_UNSUPPORTED_DNSKEY_ALG = 1, 55*5afab0e5SDag-Erling Smørgrav LDNS_EDE_UNSUPPORTED_DS_DIGEST = 2, 56*5afab0e5SDag-Erling Smørgrav LDNS_EDE_STALE_ANSWER = 3, 57*5afab0e5SDag-Erling Smørgrav LDNS_EDE_FORGED_ANSWER = 4, 58*5afab0e5SDag-Erling Smørgrav LDNS_EDE_DNSSEC_INDETERMINATE = 5, 59*5afab0e5SDag-Erling Smørgrav LDNS_EDE_DNSSEC_BOGUS = 6, 60*5afab0e5SDag-Erling Smørgrav LDNS_EDE_SIGNATURE_EXPIRED = 7, 61*5afab0e5SDag-Erling Smørgrav LDNS_EDE_SIGNATURE_NOT_YET_VALID = 8, 62*5afab0e5SDag-Erling Smørgrav LDNS_EDE_DNSKEY_MISSING = 9, 63*5afab0e5SDag-Erling Smørgrav LDNS_EDE_RRSIGS_MISSING = 10, 64*5afab0e5SDag-Erling Smørgrav LDNS_EDE_NO_ZONE_KEY_BIT_SET = 11, 65*5afab0e5SDag-Erling Smørgrav LDNS_EDE_NSEC_MISSING = 12, 66*5afab0e5SDag-Erling Smørgrav LDNS_EDE_CACHED_ERROR = 13, 67*5afab0e5SDag-Erling Smørgrav LDNS_EDE_NOT_READY = 14, 68*5afab0e5SDag-Erling Smørgrav LDNS_EDE_BLOCKED = 15, 69*5afab0e5SDag-Erling Smørgrav LDNS_EDE_CENSORED = 16, 70*5afab0e5SDag-Erling Smørgrav LDNS_EDE_FILTERED = 17, 71*5afab0e5SDag-Erling Smørgrav LDNS_EDE_PROHIBITED = 18, 72*5afab0e5SDag-Erling Smørgrav LDNS_EDE_STALE_NXDOMAIN_ANSWER = 19, 73*5afab0e5SDag-Erling Smørgrav LDNS_EDE_NOT_AUTHORITATIVE = 20, 74*5afab0e5SDag-Erling Smørgrav LDNS_EDE_NOT_SUPPORTED = 21, 75*5afab0e5SDag-Erling Smørgrav LDNS_EDE_NO_REACHABLE_AUTHORITY = 22, 76*5afab0e5SDag-Erling Smørgrav LDNS_EDE_NETWORK_ERROR = 23, 77*5afab0e5SDag-Erling Smørgrav LDNS_EDE_INVALID_DATA = 24, 78*5afab0e5SDag-Erling Smørgrav LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID = 25, 79*5afab0e5SDag-Erling Smørgrav LDNS_EDE_TOO_EARLY = 26 80*5afab0e5SDag-Erling Smørgrav }; 81*5afab0e5SDag-Erling Smørgrav typedef enum ldns_edns_enum_ede_code ldns_edns_ede_code; 82*5afab0e5SDag-Erling Smørgrav 83*5afab0e5SDag-Erling Smørgrav /** 84*5afab0e5SDag-Erling Smørgrav * The struct that stores an ordered EDNS option. 85*5afab0e5SDag-Erling Smørgrav * An EDNS option is structed as follows: 86*5afab0e5SDag-Erling Smørgrav +0 (MSB) +1 (LSB) 87*5afab0e5SDag-Erling Smørgrav +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 88*5afab0e5SDag-Erling Smørgrav 0: | OPTION-CODE | 89*5afab0e5SDag-Erling Smørgrav +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 90*5afab0e5SDag-Erling Smørgrav 2: | OPTION-LENGTH | 91*5afab0e5SDag-Erling Smørgrav +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 92*5afab0e5SDag-Erling Smørgrav 4: | | 93*5afab0e5SDag-Erling Smørgrav / OPTION-DATA / 94*5afab0e5SDag-Erling Smørgrav / / 95*5afab0e5SDag-Erling Smørgrav +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 96*5afab0e5SDag-Erling Smørgrav */ 97*5afab0e5SDag-Erling Smørgrav struct ldns_struct_edns_option { 98*5afab0e5SDag-Erling Smørgrav ldns_edns_option_code _code; 99*5afab0e5SDag-Erling Smørgrav size_t _size; 100*5afab0e5SDag-Erling Smørgrav void *_data; 101*5afab0e5SDag-Erling Smørgrav }; 102*5afab0e5SDag-Erling Smørgrav typedef struct ldns_struct_edns_option ldns_edns_option; 103*5afab0e5SDag-Erling Smørgrav 104*5afab0e5SDag-Erling Smørgrav 105*5afab0e5SDag-Erling Smørgrav /* 106*5afab0e5SDag-Erling Smørgrav * Array structure to store multiple EDNS options 107*5afab0e5SDag-Erling Smørgrav */ 108*5afab0e5SDag-Erling Smørgrav struct ldns_struct_edns_option_list 109*5afab0e5SDag-Erling Smørgrav { 110*5afab0e5SDag-Erling Smørgrav size_t _option_count; /* the number of EDNS options in the list */ 111*5afab0e5SDag-Erling Smørgrav size_t _option_capacity; /* the amount of options that fit into the list */ 112*5afab0e5SDag-Erling Smørgrav size_t _options_size; /* the total size of the options serialized */ 113*5afab0e5SDag-Erling Smørgrav ldns_edns_option **_options; 114*5afab0e5SDag-Erling Smørgrav }; 115*5afab0e5SDag-Erling Smørgrav typedef struct ldns_struct_edns_option_list ldns_edns_option_list; 116*5afab0e5SDag-Erling Smørgrav 117*5afab0e5SDag-Erling Smørgrav /* 118*5afab0e5SDag-Erling Smørgrav * Access functions 119*5afab0e5SDag-Erling Smørgrav * do this as functions to get type checking 120*5afab0e5SDag-Erling Smørgrav */ 121*5afab0e5SDag-Erling Smørgrav 122*5afab0e5SDag-Erling Smørgrav /** 123*5afab0e5SDag-Erling Smørgrav * returns the size of the EDNS data. 124*5afab0e5SDag-Erling Smørgrav * \param[in] *edns the EDNS struct to read from 125*5afab0e5SDag-Erling Smørgrav * \return uint16_t with the size 126*5afab0e5SDag-Erling Smørgrav */ 127*5afab0e5SDag-Erling Smørgrav size_t ldns_edns_get_size(const ldns_edns_option *edns); 128*5afab0e5SDag-Erling Smørgrav 129*5afab0e5SDag-Erling Smørgrav /** 130*5afab0e5SDag-Erling Smørgrav * returns the option code of the EDNS data. 131*5afab0e5SDag-Erling Smørgrav * \param[in] *edns the EDNS struct to read from 132*5afab0e5SDag-Erling Smørgrav * \return uint16_t with the size 133*5afab0e5SDag-Erling Smørgrav */ 134*5afab0e5SDag-Erling Smørgrav ldns_edns_option_code ldns_edns_get_code(const ldns_edns_option *edns); 135*5afab0e5SDag-Erling Smørgrav 136*5afab0e5SDag-Erling Smørgrav /** 137*5afab0e5SDag-Erling Smørgrav * returns the EDNS option data. 138*5afab0e5SDag-Erling Smørgrav * \param[in] *edns the EDNS option to read from 139*5afab0e5SDag-Erling Smørgrav * \return uint8_t* pointer to the EDNS option's data 140*5afab0e5SDag-Erling Smørgrav */ 141*5afab0e5SDag-Erling Smørgrav uint8_t *ldns_edns_get_data(const ldns_edns_option *edns); 142*5afab0e5SDag-Erling Smørgrav 143*5afab0e5SDag-Erling Smørgrav 144*5afab0e5SDag-Erling Smørgrav /** 145*5afab0e5SDag-Erling Smørgrav * serialise the EDNS option into wireformat. 146*5afab0e5SDag-Erling Smørgrav * \param[in] *edns the EDNS option to read from 147*5afab0e5SDag-Erling Smørgrav * \return ldns_buffer* the buffer containing the data 148*5afab0e5SDag-Erling Smørgrav */ 149*5afab0e5SDag-Erling Smørgrav ldns_buffer *ldns_edns_get_wireformat_buffer(const ldns_edns_option *edns); 150*5afab0e5SDag-Erling Smørgrav 151*5afab0e5SDag-Erling Smørgrav /* Constructors and destructors*/ 152*5afab0e5SDag-Erling Smørgrav 153*5afab0e5SDag-Erling Smørgrav /** 154*5afab0e5SDag-Erling Smørgrav * allocates a new EDNS structure and fills it. This function *DOES NOT* copy 155*5afab0e5SDag-Erling Smørgrav * the contents from the data parameter. 156*5afab0e5SDag-Erling Smørgrav * \param[in] code the EDNS code 157*5afab0e5SDag-Erling Smørgrav * \param[in] size size of the buffer 158*5afab0e5SDag-Erling Smørgrav * \param[in] data pointer to the buffer to be assigned 159*5afab0e5SDag-Erling Smørgrav * \return the new EDNS structure or NULL on failure 160*5afab0e5SDag-Erling Smørgrav */ 161*5afab0e5SDag-Erling Smørgrav ldns_edns_option *ldns_edns_new(ldns_edns_option_code code, size_t size, void *data); 162*5afab0e5SDag-Erling Smørgrav 163*5afab0e5SDag-Erling Smørgrav /** 164*5afab0e5SDag-Erling Smørgrav * allocates a new EDNS structure and fills it. This function *DOES* copy 165*5afab0e5SDag-Erling Smørgrav * the contents from the data parameter. 166*5afab0e5SDag-Erling Smørgrav * \param[in] code the EDNS code 167*5afab0e5SDag-Erling Smørgrav * \param[in] size size of the buffer 168*5afab0e5SDag-Erling Smørgrav * \param[in] data pointer to the buffer to be assigned 169*5afab0e5SDag-Erling Smørgrav * \return the new EDNS structure or NULL on failure 170*5afab0e5SDag-Erling Smørgrav */ 171*5afab0e5SDag-Erling Smørgrav ldns_edns_option *ldns_edns_new_from_data(ldns_edns_option_code code, size_t size, const void *data); 172*5afab0e5SDag-Erling Smørgrav 173*5afab0e5SDag-Erling Smørgrav /** 174*5afab0e5SDag-Erling Smørgrav * clone an EDNS option 175*5afab0e5SDag-Erling Smørgrav * \param[in] edns the EDNS option 176*5afab0e5SDag-Erling Smørgrav * \return the new EDNS structure 177*5afab0e5SDag-Erling Smørgrav */ 178*5afab0e5SDag-Erling Smørgrav ldns_edns_option *ldns_edns_clone(ldns_edns_option *edns); 179*5afab0e5SDag-Erling Smørgrav 180*5afab0e5SDag-Erling Smørgrav /** 181*5afab0e5SDag-Erling Smørgrav * free the EDNS option. Use deep_free if the _data member is allocated. 182*5afab0e5SDag-Erling Smørgrav * \param[in] edns the EDNS option to free 183*5afab0e5SDag-Erling Smørgrav */ 184*5afab0e5SDag-Erling Smørgrav void ldns_edns_deep_free(ldns_edns_option *edns); 185*5afab0e5SDag-Erling Smørgrav void ldns_edns_free(ldns_edns_option *edns); 186*5afab0e5SDag-Erling Smørgrav 187*5afab0e5SDag-Erling Smørgrav /** 188*5afab0e5SDag-Erling Smørgrav * allocates space for a new list of EDNS options 189*5afab0e5SDag-Erling Smørgrav * \return the new EDNS option list or NULL on failure 190*5afab0e5SDag-Erling Smørgrav */ 191*5afab0e5SDag-Erling Smørgrav ldns_edns_option_list* ldns_edns_option_list_new(void); 192*5afab0e5SDag-Erling Smørgrav 193*5afab0e5SDag-Erling Smørgrav /** 194*5afab0e5SDag-Erling Smørgrav * clone the EDNS options list and it's contents 195*5afab0e5SDag-Erling Smørgrav * \param[in] options_list the EDNS options_list to read from 196*5afab0e5SDag-Erling Smørgrav * \return the new EDNS option list 197*5afab0e5SDag-Erling Smørgrav */ 198*5afab0e5SDag-Erling Smørgrav ldns_edns_option_list *ldns_edns_option_list_clone(ldns_edns_option_list *options_list); 199*5afab0e5SDag-Erling Smørgrav 200*5afab0e5SDag-Erling Smørgrav /** 201*5afab0e5SDag-Erling Smørgrav * free the EDNS option list. Use deep_free to free the options options 202*5afab0e5SDag-Erling Smørgrav * in the list as well. 203*5afab0e5SDag-Erling Smørgrav * \param[in] options_list the EDNS option to free 204*5afab0e5SDag-Erling Smørgrav */ 205*5afab0e5SDag-Erling Smørgrav void ldns_edns_option_list_free(ldns_edns_option_list *options_list); 206*5afab0e5SDag-Erling Smørgrav void ldns_edns_option_list_deep_free(ldns_edns_option_list *options_list); 207*5afab0e5SDag-Erling Smørgrav 208*5afab0e5SDag-Erling Smørgrav /* edns_option_list functions */ 209*5afab0e5SDag-Erling Smørgrav 210*5afab0e5SDag-Erling Smørgrav /** 211*5afab0e5SDag-Erling Smørgrav * returns the number of options in the EDNS options list. 212*5afab0e5SDag-Erling Smørgrav * \param[in] options_list the EDNS options_list to read from 213*5afab0e5SDag-Erling Smørgrav * \return the number of EDNS options 214*5afab0e5SDag-Erling Smørgrav */ 215*5afab0e5SDag-Erling Smørgrav size_t ldns_edns_option_list_get_count(const ldns_edns_option_list *options_list); 216*5afab0e5SDag-Erling Smørgrav 217*5afab0e5SDag-Erling Smørgrav /** 218*5afab0e5SDag-Erling Smørgrav * returns the EDNS option as the specified index in the list of EDNS options. 219*5afab0e5SDag-Erling Smørgrav * \param[in] options_list the EDNS options_list to read from 220*5afab0e5SDag-Erling Smørgrav * \param[in] index the location of the EDNS option to get in the list 221*5afab0e5SDag-Erling Smørgrav * \return the EDNS option located at the index or NULL on failure 222*5afab0e5SDag-Erling Smørgrav */ 223*5afab0e5SDag-Erling Smørgrav ldns_edns_option* ldns_edns_option_list_get_option(const ldns_edns_option_list *options_list, 224*5afab0e5SDag-Erling Smørgrav size_t index); 225*5afab0e5SDag-Erling Smørgrav 226*5afab0e5SDag-Erling Smørgrav 227*5afab0e5SDag-Erling Smørgrav /** 228*5afab0e5SDag-Erling Smørgrav * returns the total size of all the individual EDNS options in the EDNS list. 229*5afab0e5SDag-Erling Smørgrav * \param[in] options_list the EDNS options_list to read from 230*5afab0e5SDag-Erling Smørgrav * \return the total size of the options combined 231*5afab0e5SDag-Erling Smørgrav */ 232*5afab0e5SDag-Erling Smørgrav size_t ldns_edns_option_list_get_options_size(const ldns_edns_option_list *options_list); 233*5afab0e5SDag-Erling Smørgrav 234*5afab0e5SDag-Erling Smørgrav /** 235*5afab0e5SDag-Erling Smørgrav * adds an EDNS option to the list of options at the specified index. Also 236*5afab0e5SDag-Erling Smørgrav * returns the option that was previously at that index. 237*5afab0e5SDag-Erling Smørgrav * \param[in] options_list the EDNS options_list to add to 238*5afab0e5SDag-Erling Smørgrav * \param[in] option the EDNS option to add to the list 239*5afab0e5SDag-Erling Smørgrav * \param[in] index the index in the list where to set the option 240*5afab0e5SDag-Erling Smørgrav * \return the EDNS option previously located at the index 241*5afab0e5SDag-Erling Smørgrav */ 242*5afab0e5SDag-Erling Smørgrav ldns_edns_option *ldns_edns_option_list_set_option(ldns_edns_option_list *options_list, 243*5afab0e5SDag-Erling Smørgrav ldns_edns_option *option, size_t index); 244*5afab0e5SDag-Erling Smørgrav 245*5afab0e5SDag-Erling Smørgrav /** 246*5afab0e5SDag-Erling Smørgrav * adds an EDNS option at the end of the list of options. 247*5afab0e5SDag-Erling Smørgrav * \param[in] options_list the EDNS options_list to add to 248*5afab0e5SDag-Erling Smørgrav * \param[in] option the (non-NULL) EDNS option to add to the list 249*5afab0e5SDag-Erling Smørgrav * \return true on success and false of failure 250*5afab0e5SDag-Erling Smørgrav */ 251*5afab0e5SDag-Erling Smørgrav bool ldns_edns_option_list_push(ldns_edns_option_list *options_list, 252*5afab0e5SDag-Erling Smørgrav ldns_edns_option *option); 253*5afab0e5SDag-Erling Smørgrav 254*5afab0e5SDag-Erling Smørgrav /** 255*5afab0e5SDag-Erling Smørgrav * removes and returns the EDNS option at the end of the list of options. 256*5afab0e5SDag-Erling Smørgrav * \param[in] options_list the EDNS options_list to add to 257*5afab0e5SDag-Erling Smørgrav * \return the EDNS option at the end of the list, or NULL on failure 258*5afab0e5SDag-Erling Smørgrav */ 259*5afab0e5SDag-Erling Smørgrav ldns_edns_option* ldns_edns_option_list_pop(ldns_edns_option_list *options_list); 260*5afab0e5SDag-Erling Smørgrav 261*5afab0e5SDag-Erling Smørgrav /** 262*5afab0e5SDag-Erling Smørgrav * serializes all the EDNS options into a single wireformat buffer 263*5afab0e5SDag-Erling Smørgrav * \param[in] option_list the EDNS options_list to combine into one wireformat 264*5afab0e5SDag-Erling Smørgrav * \return the filled buffer or NULL on failure 265*5afab0e5SDag-Erling Smørgrav */ 266*5afab0e5SDag-Erling Smørgrav ldns_buffer *ldns_edns_option_list2wireformat_buffer(const ldns_edns_option_list *option_list); 267*5afab0e5SDag-Erling Smørgrav 268*5afab0e5SDag-Erling Smørgrav #ifdef __cplusplus 269*5afab0e5SDag-Erling Smørgrav } 270*5afab0e5SDag-Erling Smørgrav #endif 271*5afab0e5SDag-Erling Smørgrav 272*5afab0e5SDag-Erling Smørgrav #endif /* LDNS_EDNS_H */ 273