xref: /freebsd/contrib/ldns/ldns/edns.h (revision 9ed998a81bab54203604d08293089db875758686)
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