1 /*
2 * coap_option.h -- helpers for handling options in CoAP PDUs
3 *
4 * Copyright (C) 2010-2013,2022-2023 Olaf Bergmann <bergmann@tzi.org>
5 *
6 * SPDX-License-Identifier: BSD-2-Clause
7 *
8 * This file is part of the CoAP library libcoap. Please see README for terms
9 * of use.
10 */
11
12 /**
13 * @file coap_option.h
14 * @brief Helpers for handling options in CoAP PDUs
15 */
16
17 #ifndef COAP_OPTION_H_
18 #define COAP_OPTION_H_
19
20 typedef uint16_t coap_option_num_t;
21
22 /**
23 * Use byte-oriented access methods here because sliding a complex struct
24 * coap_opt_t over the data buffer may cause bus error on certain platforms.
25 */
26 typedef uint8_t coap_opt_t;
27 #define PCHAR(p) ((coap_opt_t *)(p))
28
29 /**
30 * Representation of CoAP options.
31 */
32 typedef struct {
33 uint16_t delta;
34 size_t length;
35 const uint8_t *value;
36 } coap_option_t;
37
38 /**
39 * Parses the option pointed to by @p opt into @p result. This function returns
40 * the number of bytes that have been parsed, or @c 0 on error. An error is
41 * signaled when illegal delta or length values are encountered or when option
42 * parsing would result in reading past the option (i.e. beyond opt + length).
43 *
44 * @param opt The beginning of the option to parse.
45 * @param length The maximum length of @p opt.
46 * @param result A pointer to the coap_option_t structure that is filled with
47 * actual values iff coap_opt_parse() > 0.
48 * @return The number of bytes parsed or @c 0 on error.
49 */
50 size_t coap_opt_parse(const coap_opt_t *opt,
51 size_t length,
52 coap_option_t *result);
53
54 /**
55 * Returns the size of the given option, taking into account a possible option
56 * jump.
57 *
58 * @param opt An option jump or the beginning of the option.
59 * @return The number of bytes between @p opt and the end of the option
60 * starting at @p opt. In case of an error, this function returns
61 * @c 0 as options need at least one byte storage space.
62 */
63 size_t coap_opt_size(const coap_opt_t *opt);
64
65 /**
66 * @ingroup application_api
67 * @defgroup opt_filter Option Filters
68 * API for access option filters
69 * @{
70 */
71
72 /**
73 * The number of option types below 256 that can be stored in an
74 * option filter. COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be
75 * at most 16. Each coap_option_filter_t object reserves
76 * ((COAP_OPT_FILTER_SHORT + 1) / 2) * 2 bytes for short options.
77 */
78 #define COAP_OPT_FILTER_SHORT 6
79
80 /**
81 * The number of option types above 255 that can be stored in an
82 * option filter. COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be
83 * at most 16. Each coap_option_filter_t object reserves
84 * COAP_OPT_FILTER_LONG * 2 bytes for short options.
85 */
86 #define COAP_OPT_FILTER_LONG 2
87
88 /* Ensure that COAP_OPT_FILTER_SHORT and COAP_OPT_FILTER_LONG are set
89 * correctly. */
90 #if (COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG > 16)
91 #error COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be less or equal 16
92 #endif /* (COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG > 16) */
93
94 /*
95 * mask contains a bit vector that indicates which fields in the long_opts[]
96 * and subsequent short_opts[] are used. The first COAP_OPT_FILTER_LONG bits
97 * correspond to the long option types that are stored in long_opts[]
98 * elements. The next COAP_OPT_FILTER_SHORT bits correspond to the short
99 * option types that are stored in short_opts[].
100 */
101 typedef struct coap_opt_filter_t {
102 uint16_t mask;
103 uint16_t long_opts[COAP_OPT_FILTER_LONG];
104 uint8_t short_opts[COAP_OPT_FILTER_SHORT];
105 } coap_opt_filter_t;
106
107 /** Pre-defined filter that includes all options. */
108 #define COAP_OPT_ALL NULL
109
110 /**
111 * Clears filter @p filter.
112 *
113 * @param filter The filter to clear.
114 */
115 void coap_option_filter_clear(coap_opt_filter_t *filter);
116
117 /**
118 * Sets the corresponding entry for @p number in @p filter. This
119 * function returns @c 1 if bit was set or @c 0 on error (i.e. when
120 * there is not enough space to fit the given number in the filter).
121 *
122 * @param filter The filter object to change.
123 * @param number The option number for which the bit should be set.
124 *
125 * @return @c 1 if bit was set, @c 0 otherwise.
126 */
127 int coap_option_filter_set(coap_opt_filter_t *filter, coap_option_num_t number);
128
129 /**
130 * Clears the corresponding entry for @p number in @p filter. This
131 * function returns @c 1 if bit was set or @c 0 if not previously set.
132 *
133 * @param filter The filter object to change.
134 * @param number The option number that should be cleared from the filter.
135 *
136 * @return @c 1 if bit was cleared, @c 0 otherwise.
137 */
138 int coap_option_filter_unset(coap_opt_filter_t *filter,
139 coap_option_num_t number);
140
141 /**
142 * Checks if @p number is contained in @p filter. This function returns
143 * @c 1 if found, @c 0 if not.
144 *
145 * @param filter The filter object to search.
146 * @param number The option number to search for.
147 *
148 * @return @c 1 if @p number was found, @c 0 otherwise
149 */
150 int coap_option_filter_get(coap_opt_filter_t *filter, coap_option_num_t number);
151
152 /**
153 * Iterator to run through PDU options. This object must be
154 * initialized with coap_option_iterator_init(). Call
155 * coap_option_next() to walk through the list of options until
156 * coap_option_next() returns @c NULL.
157 *
158 * @code
159 * coap_opt_t *option;
160 * coap_opt_iterator_t opt_iter;
161 * coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL);
162 *
163 * while ((option = coap_option_next(&opt_iter))) {
164 * ... do something with option ...
165 * }
166 * @endcode
167 */
168 typedef struct {
169 size_t length; /**< remaining length of PDU */
170 coap_option_num_t number; /**< decoded option number */
171 unsigned int bad:1; /**< iterator object is ok if not set */
172 unsigned int filtered:1; /**< denotes whether or not filter is used */
173 coap_opt_t *next_option; /**< pointer to the unparsed next option */
174 coap_opt_filter_t filter; /**< option filter */
175 } coap_opt_iterator_t;
176
177 /**
178 * Initializes the given option iterator @p oi to point to the beginning of the
179 * @p pdu's option list. This function returns @p oi on success, @c NULL
180 * otherwise (i.e. when no options exist). Note that a length check on the
181 * option list must be performed before coap_option_iterator_init() is called.
182 *
183 * @param pdu The PDU the options of which should be walked through.
184 * @param oi An iterator object that will be initilized.
185 * @param filter An optional option number filter.
186 * With @p number != @c COAP_OPT_ALL, coap_option_next()
187 * will return only options matching this bitmask.
188 * Fence-post options @c 14, @c 28, @c 42, ... are always
189 * skipped.
190 *
191 * @return The iterator object @p oi on success, @c NULL otherwise.
192 */
193 coap_opt_iterator_t *coap_option_iterator_init(const coap_pdu_t *pdu,
194 coap_opt_iterator_t *oi,
195 const coap_opt_filter_t *filter);
196
197 /**
198 * Updates the iterator @p oi to point to the next option. This function returns
199 * a pointer to that option or @c NULL if no more options exist. The contents of
200 * @p oi will be updated. In particular, @c oi->n specifies the current option's
201 * ordinal number (counted from @c 1), @c oi->number is the option's number
202 * value, and @c oi->option points to the beginning of the current option
203 * itself. When * advanced past the last option, @c oi->option will be @c NULL.
204 *
205 * Note that options are skipped whose corresponding bits in the filter
206 * specified with coap_option_iterator_init() are @c 0. Options with numbers
207 * that do not fit in this filter hence will always be returned.
208 *
209 * @param oi The option iterator to update.
210 *
211 * @return The next option or @c NULL if no more options exist.
212 */
213 coap_opt_t *coap_option_next(coap_opt_iterator_t *oi);
214
215 /**
216 * Retrieves the first option of number @p number from @p pdu. @p oi must
217 * point to a coap_opt_iterator_t object that will be initialized by this
218 * function to filter only options with number @p number. This function returns
219 * the first option with this number, or @c NULL if not found.
220 *
221 * @param pdu The PDU to parse for options.
222 * @param number The option number to search for.
223 * @param oi An iterator object to use.
224 *
225 * @return A pointer to the first option of number @p number, or @c NULL if
226 * not found.
227 */
228 coap_opt_t *coap_check_option(const coap_pdu_t *pdu,
229 coap_option_num_t number,
230 coap_opt_iterator_t *oi);
231
232 /**
233 * Encodes the given delta and length values into @p opt. This function returns
234 * the number of bytes that were required to encode @p delta and @p length or @c
235 * 0 on error. Note that the result indicates by how many bytes @p opt must be
236 * advanced to encode the option value.
237 *
238 * @param opt The option buffer space where @p delta and @p length are
239 * written.
240 * @param maxlen The maximum length of @p opt.
241 * @param delta The actual delta value to encode.
242 * @param length The actual length value to encode.
243 *
244 * @return The number of bytes used or @c 0 on error.
245 */
246 size_t coap_opt_setheader(coap_opt_t *opt,
247 size_t maxlen,
248 uint16_t delta,
249 size_t length);
250
251 /**
252 * Compute storage bytes needed for an option with given @p delta and
253 * @p length
254 *
255 * @param delta The option delta.
256 * @param length The option length.
257 *
258 * @return The number of bytes required to encode this option.
259 */
260 size_t coap_opt_encode_size(uint16_t delta, size_t length);
261
262 /**
263 * Encodes option with given @p delta into @p opt. This function returns the
264 * number of bytes written to @p opt or @c 0 on error. This happens especially
265 * when @p opt does not provide sufficient space to store the option value,
266 * delta, and option jumps when required.
267 *
268 * @param opt The option buffer space where @p val is written.
269 * @param n Maximum length of @p opt.
270 * @param delta The option delta.
271 * @param val The option value to copy into @p opt.
272 * @param length The actual length of @p val.
273 *
274 * @return The number of bytes that have been written to @p opt or @c 0 on
275 * error. The return value will always be less than @p n.
276 */
277 size_t coap_opt_encode(coap_opt_t *opt,
278 size_t n,
279 uint16_t delta,
280 const uint8_t *val,
281 size_t length);
282
283 /**
284 * Returns the length of the given option. @p opt must point to an option jump
285 * or the beginning of the option. This function returns @c 0 when @p opt is not
286 * an option or the actual length of @p opt (which can be @c 0 as well).
287 *
288 * @note {The rationale for using @c 0 in case of an error is that in most
289 * contexts, the result of this function is used to skip the next
290 * coap_opt_length() bytes.}
291 *
292 * @param opt The option whose length should be returned.
293 *
294 * @return The option's length or @c 0 when undefined.
295 */
296 uint32_t coap_opt_length(const coap_opt_t *opt);
297
298 /**
299 * Returns a pointer to the value of the given option. @p opt must point to an
300 * option jump or the beginning of the option. This function returns @c NULL if
301 * @p opt is not a valid option.
302 *
303 * @param opt The option whose value should be returned.
304 *
305 * @return A pointer to the option value or @c NULL on error.
306 */
307 const uint8_t *coap_opt_value(const coap_opt_t *opt);
308
309 /**
310 * Representation of chained list of CoAP options to install.
311 *
312 * @code
313 * coap_optlist_t *optlist_chain = NULL;
314 * coap_pdu_t *pdu = coap_new_pdu(session);
315 *
316 * ... other set up code ...
317 * coap_insert_optlist(&optlist_chain, coap_new_optlist(COAP_OPTION_OBSERVE,
318 * COAP_OBSERVE_ESTABLISH, NULL));
319 *
320 * coap_add_optlist_pdu(pdu, &optlist_chain);
321 * ... other code ...
322 * coap_delete_optlist(optlist_chain);
323 * @endcode
324 */
325 typedef struct coap_optlist_t {
326 struct coap_optlist_t *next; /**< next entry in the optlist chain */
327 uint16_t number; /**< the option number (no delta coding) */
328 size_t length; /**< the option value length */
329 uint8_t *data; /**< the option data */
330 } coap_optlist_t;
331
332 /**
333 * Create a new optlist entry.
334 *
335 * Note: Where possible, the option data needs to be stripped of leading zeros
336 * (big endian) to reduce the amount of data needed in the PDU, as well as in
337 * some cases the maximum data size of an opton can be exceeded if not stripped
338 * and hence be illegal. This is done by using coap_encode_var_safe() or
339 * coap_encode_var_safe8().
340 *
341 * @param number The option number (COAP_OPTION_*)
342 * @param length The option length
343 * @param data The option value data
344 *
345 * @return A pointer to the new optlist entry, or @c NULL if error
346 */
347 coap_optlist_t *coap_new_optlist(uint16_t number,
348 size_t length,
349 const uint8_t *data);
350
351 /**
352 * The current optlist of @p optlist_chain is first sorted (as per RFC7272
353 * ordering requirements) and then added to the @p pdu.
354 *
355 * @param pdu The pdu to add the options to from the chain list
356 * @param optlist_chain The chained list of optlist to add to the pdu
357 *
358 * @return @c 1 if succesful or @c 0 if failure;
359 */
360 int coap_add_optlist_pdu(coap_pdu_t *pdu, coap_optlist_t **optlist_chain);
361
362 /**
363 * Adds @p optlist to the given @p optlist_chain. The optlist_chain variable
364 * be set to NULL before the initial call to coap_insert_optlist().
365 * The optlist_chain will need to be deleted using coap_delete_optlist()
366 * when no longer required.
367 *
368 * @param optlist_chain The chain to add optlist to
369 * @param optlist The optlist to add to the queue
370 *
371 * @return @c 1 if successful, @c 0 otherwise.
372 */
373 int coap_insert_optlist(coap_optlist_t **optlist_chain,
374 coap_optlist_t *optlist);
375
376 /**
377 * Removes all entries from the @p optlist_chain, freeing off their
378 * memory usage.
379 *
380 * @param optlist_chain The optlist chain to remove all the entries from
381 */
382 void coap_delete_optlist(coap_optlist_t *optlist_chain);
383
384 /** @} */
385
386 /**
387 * Sets the corresponding bit for @p type in @p filter. This function returns @c
388 * 1 if bit was set or @c -1 on error (i.e. when the given type does not fit in
389 * the filter).
390 *
391 * @deprecated Use coap_option_filter_set() instead.
392 *
393 * @param filter The filter object to change.
394 * @param type The type for which the bit should be set.
395 *
396 * @return @c 1 if bit was set, @c -1 otherwise.
397 */
398 COAP_STATIC_INLINE COAP_DEPRECATED int
coap_option_setb(coap_opt_filter_t * filter,uint16_t type)399 coap_option_setb(coap_opt_filter_t *filter, uint16_t type) {
400 return coap_option_filter_set(filter, type) ? 1 : -1;
401 }
402
403 /**
404 * Clears the corresponding bit for @p type in @p filter. This function returns
405 * @c 1 if bit was cleared or @c -1 on error (i.e. bit not set).
406 *
407 * @deprecated Use coap_option_filter_unset() instead.
408 *
409 * @param filter The filter object to change.
410 * @param type The type for which the bit should be cleared.
411 *
412 * @return @c 1 if bit was set, @c -1 otherwise.
413 */
414 COAP_STATIC_INLINE COAP_DEPRECATED int
coap_option_clrb(coap_opt_filter_t * filter,uint16_t type)415 coap_option_clrb(coap_opt_filter_t *filter, uint16_t type) {
416 return coap_option_filter_unset(filter, type) ? 1 : -1;
417 }
418
419 /**
420 * Gets the corresponding bit for @p type in @p filter. This function returns @c
421 * 1 if the bit is set @c 0 if not.
422 *
423 * @deprecated Use coap_option_filter_get() instead.
424 *
425 * @param filter The filter object to read bit from.
426 * @param type The type for which the bit should be read.
427 *
428 * @return @c 1 if bit was set, @c 0 if not.
429 */
430 COAP_STATIC_INLINE COAP_DEPRECATED int
coap_option_getb(coap_opt_filter_t * filter,uint16_t type)431 coap_option_getb(coap_opt_filter_t *filter, uint16_t type) {
432 return coap_option_filter_get(filter, type);
433 }
434
435 #endif /* COAP_OPTION_H_ */
436