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