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 80 }; 81 typedef enum ldns_edns_enum_ede_code ldns_edns_ede_code; 82 83 /** 84 * The struct that stores an ordered EDNS option. 85 * An EDNS option is structed as follows: 86 +0 (MSB) +1 (LSB) 87 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 88 0: | OPTION-CODE | 89 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 90 2: | OPTION-LENGTH | 91 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 92 4: | | 93 / OPTION-DATA / 94 / / 95 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 96 */ 97 struct ldns_struct_edns_option { 98 ldns_edns_option_code _code; 99 size_t _size; 100 void *_data; 101 }; 102 typedef struct ldns_struct_edns_option ldns_edns_option; 103 104 105 /* 106 * Array structure to store multiple EDNS options 107 */ 108 struct ldns_struct_edns_option_list 109 { 110 size_t _option_count; /* the number of EDNS options in the list */ 111 size_t _option_capacity; /* the amount of options that fit into the list */ 112 size_t _options_size; /* the total size of the options serialized */ 113 ldns_edns_option **_options; 114 }; 115 typedef struct ldns_struct_edns_option_list ldns_edns_option_list; 116 117 /* 118 * Access functions 119 * do this as functions to get type checking 120 */ 121 122 /** 123 * returns the size of the EDNS data. 124 * \param[in] *edns the EDNS struct to read from 125 * \return uint16_t with the size 126 */ 127 size_t ldns_edns_get_size(const ldns_edns_option *edns); 128 129 /** 130 * returns the option code of the EDNS data. 131 * \param[in] *edns the EDNS struct to read from 132 * \return uint16_t with the size 133 */ 134 ldns_edns_option_code ldns_edns_get_code(const ldns_edns_option *edns); 135 136 /** 137 * returns the EDNS option data. 138 * \param[in] *edns the EDNS option to read from 139 * \return uint8_t* pointer to the EDNS option's data 140 */ 141 uint8_t *ldns_edns_get_data(const ldns_edns_option *edns); 142 143 144 /** 145 * serialise the EDNS option into wireformat. 146 * \param[in] *edns the EDNS option to read from 147 * \return ldns_buffer* the buffer containing the data 148 */ 149 ldns_buffer *ldns_edns_get_wireformat_buffer(const ldns_edns_option *edns); 150 151 /* Constructors and destructors*/ 152 153 /** 154 * allocates a new EDNS structure and fills it. This function *DOES NOT* copy 155 * the contents from the data parameter. 156 * \param[in] code the EDNS code 157 * \param[in] size size of the buffer 158 * \param[in] data pointer to the buffer to be assigned 159 * \return the new EDNS structure or NULL on failure 160 */ 161 ldns_edns_option *ldns_edns_new(ldns_edns_option_code code, size_t size, void *data); 162 163 /** 164 * allocates a new EDNS structure and fills it. This function *DOES* copy 165 * the contents from the data parameter. 166 * \param[in] code the EDNS code 167 * \param[in] size size of the buffer 168 * \param[in] data pointer to the buffer to be assigned 169 * \return the new EDNS structure or NULL on failure 170 */ 171 ldns_edns_option *ldns_edns_new_from_data(ldns_edns_option_code code, size_t size, const void *data); 172 173 /** 174 * clone an EDNS option 175 * \param[in] edns the EDNS option 176 * \return the new EDNS structure 177 */ 178 ldns_edns_option *ldns_edns_clone(ldns_edns_option *edns); 179 180 /** 181 * free the EDNS option. Use deep_free if the _data member is allocated. 182 * \param[in] edns the EDNS option to free 183 */ 184 void ldns_edns_deep_free(ldns_edns_option *edns); 185 void ldns_edns_free(ldns_edns_option *edns); 186 187 /** 188 * allocates space for a new list of EDNS options 189 * \return the new EDNS option list or NULL on failure 190 */ 191 ldns_edns_option_list* ldns_edns_option_list_new(void); 192 193 /** 194 * clone the EDNS options list and it's contents 195 * \param[in] options_list the EDNS options_list to read from 196 * \return the new EDNS option list 197 */ 198 ldns_edns_option_list *ldns_edns_option_list_clone(ldns_edns_option_list *options_list); 199 200 /** 201 * free the EDNS option list. Use deep_free to free the options options 202 * in the list as well. 203 * \param[in] options_list the EDNS option to free 204 */ 205 void ldns_edns_option_list_free(ldns_edns_option_list *options_list); 206 void ldns_edns_option_list_deep_free(ldns_edns_option_list *options_list); 207 208 /* edns_option_list functions */ 209 210 /** 211 * returns the number of options in the EDNS options list. 212 * \param[in] options_list the EDNS options_list to read from 213 * \return the number of EDNS options 214 */ 215 size_t ldns_edns_option_list_get_count(const ldns_edns_option_list *options_list); 216 217 /** 218 * returns the EDNS option as the specified index in the list of EDNS options. 219 * \param[in] options_list the EDNS options_list to read from 220 * \param[in] index the location of the EDNS option to get in the list 221 * \return the EDNS option located at the index or NULL on failure 222 */ 223 ldns_edns_option* ldns_edns_option_list_get_option(const ldns_edns_option_list *options_list, 224 size_t index); 225 226 227 /** 228 * returns the total size of all the individual EDNS options in the EDNS list. 229 * \param[in] options_list the EDNS options_list to read from 230 * \return the total size of the options combined 231 */ 232 size_t ldns_edns_option_list_get_options_size(const ldns_edns_option_list *options_list); 233 234 /** 235 * adds an EDNS option to the list of options at the specified index. Also 236 * returns the option that was previously at that index. 237 * \param[in] options_list the EDNS options_list to add to 238 * \param[in] option the EDNS option to add to the list 239 * \param[in] index the index in the list where to set the option 240 * \return the EDNS option previously located at the index 241 */ 242 ldns_edns_option *ldns_edns_option_list_set_option(ldns_edns_option_list *options_list, 243 ldns_edns_option *option, size_t index); 244 245 /** 246 * adds an EDNS option at the end of the list of options. 247 * \param[in] options_list the EDNS options_list to add to 248 * \param[in] option the (non-NULL) EDNS option to add to the list 249 * \return true on success and false of failure 250 */ 251 bool ldns_edns_option_list_push(ldns_edns_option_list *options_list, 252 ldns_edns_option *option); 253 254 /** 255 * removes and returns the EDNS option at the end of the list of options. 256 * \param[in] options_list the EDNS options_list to add to 257 * \return the EDNS option at the end of the list, or NULL on failure 258 */ 259 ldns_edns_option* ldns_edns_option_list_pop(ldns_edns_option_list *options_list); 260 261 /** 262 * serializes all the EDNS options into a single wireformat buffer 263 * \param[in] option_list the EDNS options_list to combine into one wireformat 264 * \return the filled buffer or NULL on failure 265 */ 266 ldns_buffer *ldns_edns_option_list2wireformat_buffer(const ldns_edns_option_list *option_list); 267 268 #ifdef __cplusplus 269 } 270 #endif 271 272 #endif /* LDNS_EDNS_H */ 273