1 /*
2 * Copyright (c) 2016, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /*
29 * -------------------------------------------------------------------
30 *
31 * ## Unit Test ##
32 *
33 * This file includes its own unit test. To compile the unit test,
34 * simply compile this file with the macro SPINEL_SELF_TEST set to 1.
35 * For example:
36 *
37 * cc spinel.c -Wall -DSPINEL_SELF_TEST=1 -o spinel
38 *
39 * -------------------------------------------------------------------
40 */
41
42 // ----------------------------------------------------------------------------
43 // MARK: -
44 // MARK: Headers
45
46 #include "spinel.h"
47
48 #include <errno.h>
49
50 #ifndef SPINEL_PLATFORM_HEADER
51 /* These are all already included in the spinel platform header
52 * if SPINEL_PLATFORM_HEADER was defined.
53 */
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #endif // #ifndef SPINEL_PLATFORM_HEADER
58
59 // ----------------------------------------------------------------------------
60 // MARK: -
61
62 // IAR's errno.h apparently doesn't define EOVERFLOW.
63 #ifndef EOVERFLOW
64 // There is no real good choice for what to set
65 // errno to in this case, so we just pick the
66 // value '1' somewhat arbitrarily.
67 #define EOVERFLOW 1
68 #endif
69
70 // IAR's errno.h apparently doesn't define EINVAL.
71 #ifndef EINVAL
72 // There is no real good choice for what to set
73 // errno to in this case, so we just pick the
74 // value '1' somewhat arbitrarily.
75 #define EINVAL 1
76 #endif
77
78 // IAR's errno.h apparently doesn't define ENOMEM.
79 #ifndef ENOMEM
80 // There is no real good choice for what to set
81 // errno to in this case, so we just pick the
82 // value '1' somewhat arbitrarily.
83 #define ENOMEM 1
84 #endif
85
86 #ifndef SPINEL_PLATFORM_SHOULD_LOG_ASSERTS
87 #define SPINEL_PLATFORM_SHOULD_LOG_ASSERTS 0
88 #endif
89
90 #ifndef SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
91 #define SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR 0
92 #endif
93
94 #ifndef SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF
95 #define SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF 0
96 #endif
97
98 #ifndef SPINEL_SELF_TEST
99 #define SPINEL_SELF_TEST 0
100 #endif
101
102 #if defined(errno) && SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
103 #error "SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR is set but errno is already defined."
104 #endif
105
106 // Work-around for platforms that don't implement the `errno` variable.
107 #if !defined(errno) && SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
108 static int spinel_errno_workaround_;
109 #define errno spinel_errno_workaround_
110 #endif // SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
111
112 #ifndef assert_printf
113 #if SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF
114 #define assert_printf(fmt, ...) printf(__FILE__ ":%d: " fmt "\n", __LINE__, __VA_ARGS__)
115 #else // if SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF
116 #define assert_printf(fmt, ...) fprintf(stderr, __FILE__ ":%d: " fmt "\n", __LINE__, __VA_ARGS__)
117 #endif // else SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF
118 #endif
119
120 #ifndef require_action
121 #if SPINEL_PLATFORM_SHOULD_LOG_ASSERTS
122 #define require_action(c, l, a) \
123 do \
124 { \
125 if (!(c)) \
126 { \
127 assert_printf("Requirement Failed (%s)", #c); \
128 a; \
129 goto l; \
130 } \
131 } while (0)
132 #else // if DEBUG
133 #define require_action(c, l, a) \
134 do \
135 { \
136 if (!(c)) \
137 { \
138 a; \
139 goto l; \
140 } \
141 } while (0)
142 #endif // else DEBUG
143 #endif // ifndef require_action
144
145 #ifndef require
146 #define require(c, l) require_action(c, l, {})
147 #endif
148
149 #ifndef strnlen
spinel_strnlen(const char * s,size_t maxlen)150 static size_t spinel_strnlen(const char *s, size_t maxlen)
151 {
152 size_t ret;
153
154 for (ret = 0; (ret < maxlen) && (s[ret] != 0); ret++)
155 {
156 // Empty loop.
157 }
158
159 return ret;
160 }
161 #else
162 #define spinel_strnlen strnlen
163 #endif
164
165 typedef struct
166 {
167 va_list obj;
168 } va_list_obj;
169
170 #define SPINEL_MAX_PACK_LENGTH 32767
171
172 // ----------------------------------------------------------------------------
173
174 // This function validates whether a given byte sequence (string) follows UTF8 encoding.
spinel_validate_utf8(const uint8_t * string)175 static bool spinel_validate_utf8(const uint8_t *string)
176 {
177 bool ret = true;
178 uint8_t byte;
179 uint8_t continuation_bytes = 0;
180
181 while ((byte = *string++) != 0)
182 {
183 if ((byte & 0x80) == 0)
184 {
185 continue;
186 }
187
188 // This is a leading byte 1xxx-xxxx.
189
190 if ((byte & 0x40) == 0) // 10xx-xxxx
191 {
192 // We got a continuation byte pattern without seeing a leading byte earlier.
193 ret = false;
194 goto bail;
195 }
196 else if ((byte & 0x20) == 0) // 110x-xxxx
197 {
198 continuation_bytes = 1;
199 }
200 else if ((byte & 0x10) == 0) // 1110-xxxx
201 {
202 continuation_bytes = 2;
203 }
204 else if ((byte & 0x08) == 0) // 1111-0xxx
205 {
206 continuation_bytes = 3;
207 }
208 else // 1111-1xxx (invalid pattern).
209 {
210 ret = false;
211 goto bail;
212 }
213
214 while (continuation_bytes-- != 0)
215 {
216 byte = *string++;
217
218 // Verify the continuation byte pattern 10xx-xxxx
219 if ((byte & 0xc0) != 0x80)
220 {
221 ret = false;
222 goto bail;
223 }
224 }
225 }
226
227 bail:
228 return ret;
229 }
230
231 // ----------------------------------------------------------------------------
232 // MARK: -
233
spinel_packed_uint_decode(const uint8_t * bytes,spinel_size_t len,unsigned int * value_ptr)234 spinel_ssize_t spinel_packed_uint_decode(const uint8_t *bytes, spinel_size_t len, unsigned int *value_ptr)
235 {
236 spinel_ssize_t ret = 0;
237 unsigned int value = 0;
238
239 unsigned int i = 0;
240
241 do
242 {
243 if ((len < sizeof(uint8_t)) || (i >= sizeof(unsigned int) * SPINEL_BITS_PER_BYTE))
244 {
245 ret = -1;
246 break;
247 }
248
249 value |= (unsigned int)(bytes[0] & 0x7F) << i;
250 i += 7;
251 ret += sizeof(uint8_t);
252 bytes += sizeof(uint8_t);
253 len -= sizeof(uint8_t);
254 } while ((bytes[-1] & 0x80) == 0x80);
255
256 if ((ret > 0) && (value_ptr != NULL))
257 {
258 *value_ptr = value;
259 }
260
261 return ret;
262 }
263
spinel_packed_uint_size(unsigned int value)264 spinel_ssize_t spinel_packed_uint_size(unsigned int value)
265 {
266 spinel_ssize_t ret;
267
268 if (value < (1 << 7))
269 {
270 ret = 1;
271 }
272 else if (value < (1 << 14))
273 {
274 ret = 2;
275 }
276 else if (value < (1 << 21))
277 {
278 ret = 3;
279 }
280 else if (value < (1 << 28))
281 {
282 ret = 4;
283 }
284 else
285 {
286 ret = 5;
287 }
288
289 return ret;
290 }
291
spinel_packed_uint_encode(uint8_t * bytes,spinel_size_t len,unsigned int value)292 spinel_ssize_t spinel_packed_uint_encode(uint8_t *bytes, spinel_size_t len, unsigned int value)
293 {
294 const spinel_ssize_t encoded_size = spinel_packed_uint_size(value);
295
296 if ((spinel_ssize_t)len >= encoded_size)
297 {
298 spinel_ssize_t i;
299
300 for (i = 0; i != encoded_size - 1; ++i)
301 {
302 *bytes++ = (value & 0x7F) | 0x80;
303 value = (value >> 7);
304 }
305
306 *bytes++ = (value & 0x7F);
307 }
308
309 return encoded_size;
310 }
311
spinel_next_packed_datatype(const char * pack_format)312 const char *spinel_next_packed_datatype(const char *pack_format)
313 {
314 int depth = 0;
315
316 do
317 {
318 switch (*++pack_format)
319 {
320 case '(':
321 depth++;
322 break;
323
324 case ')':
325 depth--;
326
327 if (depth == 0)
328 {
329 pack_format++;
330 }
331
332 break;
333 }
334 } while ((depth > 0) && *pack_format != 0);
335
336 return pack_format;
337 }
338
spinel_datatype_vunpack_(bool in_place,const uint8_t * data_in,spinel_size_t data_len,const char * pack_format,va_list_obj * args)339 static spinel_ssize_t spinel_datatype_vunpack_(bool in_place,
340 const uint8_t *data_in,
341 spinel_size_t data_len,
342 const char *pack_format,
343 va_list_obj *args)
344 {
345 spinel_ssize_t ret = 0;
346
347 // Buffer length sanity check
348 require_action(data_len <= SPINEL_MAX_PACK_LENGTH, bail, (ret = -1, errno = EINVAL));
349
350 for (; *pack_format != 0; pack_format = spinel_next_packed_datatype(pack_format))
351 {
352 if (*pack_format == ')')
353 {
354 // Don't go past the end of a struct.
355 break;
356 }
357
358 switch ((spinel_datatype_t)pack_format[0])
359 {
360 case SPINEL_DATATYPE_BOOL_C:
361 {
362 bool *arg_ptr = va_arg(args->obj, bool *);
363 require_action(data_len >= sizeof(uint8_t), bail, (ret = -1, errno = EOVERFLOW));
364
365 if (arg_ptr)
366 {
367 *arg_ptr = data_in[0] != 0;
368 }
369
370 ret += sizeof(uint8_t);
371 data_in += sizeof(uint8_t);
372 data_len -= sizeof(uint8_t);
373 break;
374 }
375
376 case SPINEL_DATATYPE_INT8_C:
377 case SPINEL_DATATYPE_UINT8_C:
378 {
379 uint8_t *arg_ptr = va_arg(args->obj, uint8_t *);
380 require_action(data_len >= sizeof(uint8_t), bail, (ret = -1, errno = EOVERFLOW));
381
382 if (arg_ptr)
383 {
384 *arg_ptr = data_in[0];
385 }
386
387 ret += sizeof(uint8_t);
388 data_in += sizeof(uint8_t);
389 data_len -= sizeof(uint8_t);
390 break;
391 }
392
393 case SPINEL_DATATYPE_INT16_C:
394 case SPINEL_DATATYPE_UINT16_C:
395 {
396 uint16_t *arg_ptr = va_arg(args->obj, uint16_t *);
397 require_action(data_len >= sizeof(uint16_t), bail, (ret = -1, errno = EOVERFLOW));
398
399 if (arg_ptr)
400 {
401 *arg_ptr = (uint16_t)((data_in[1] << 8) | data_in[0]);
402 }
403
404 ret += sizeof(uint16_t);
405 data_in += sizeof(uint16_t);
406 data_len -= sizeof(uint16_t);
407 break;
408 }
409
410 case SPINEL_DATATYPE_INT32_C:
411 case SPINEL_DATATYPE_UINT32_C:
412 {
413 uint32_t *arg_ptr = va_arg(args->obj, uint32_t *);
414 require_action(data_len >= sizeof(uint32_t), bail, (ret = -1, errno = EOVERFLOW));
415
416 if (arg_ptr)
417 {
418 *arg_ptr = (uint32_t)((data_in[3] << 24) | (data_in[2] << 16) | (data_in[1] << 8) | data_in[0]);
419 }
420
421 ret += sizeof(uint32_t);
422 data_in += sizeof(uint32_t);
423 data_len -= sizeof(uint32_t);
424 break;
425 }
426
427 case SPINEL_DATATYPE_INT64_C:
428 case SPINEL_DATATYPE_UINT64_C:
429 {
430 uint64_t *arg_ptr = va_arg(args->obj, uint64_t *);
431 require_action(data_len >= sizeof(uint64_t), bail, (ret = -1, errno = EOVERFLOW));
432
433 if (arg_ptr)
434 {
435 uint32_t l32 = (uint32_t)((data_in[3] << 24) | (data_in[2] << 16) | (data_in[1] << 8) | data_in[0]);
436 uint32_t h32 = (uint32_t)((data_in[7] << 24) | (data_in[6] << 16) | (data_in[5] << 8) | data_in[4]);
437
438 *arg_ptr = ((uint64_t)l32) | (((uint64_t)h32) << 32);
439 }
440
441 ret += sizeof(uint64_t);
442 data_in += sizeof(uint64_t);
443 data_len -= sizeof(uint64_t);
444 break;
445 }
446
447 case SPINEL_DATATYPE_IPv6ADDR_C:
448 {
449 require_action(data_len >= sizeof(spinel_ipv6addr_t), bail, (ret = -1, errno = EOVERFLOW));
450
451 if (in_place)
452 {
453 spinel_ipv6addr_t *arg = va_arg(args->obj, spinel_ipv6addr_t *);
454 if (arg)
455 {
456 memcpy(arg, data_in, sizeof(spinel_ipv6addr_t));
457 }
458 }
459 else
460 {
461 const spinel_ipv6addr_t **arg_ptr = va_arg(args->obj, const spinel_ipv6addr_t **);
462 if (arg_ptr)
463 {
464 *arg_ptr = (const spinel_ipv6addr_t *)data_in;
465 }
466 }
467
468 ret += sizeof(spinel_ipv6addr_t);
469 data_in += sizeof(spinel_ipv6addr_t);
470 data_len -= sizeof(spinel_ipv6addr_t);
471 break;
472 }
473
474 case SPINEL_DATATYPE_EUI64_C:
475 {
476 require_action(data_len >= sizeof(spinel_eui64_t), bail, (ret = -1, errno = EOVERFLOW));
477
478 if (in_place)
479 {
480 spinel_eui64_t *arg = va_arg(args->obj, spinel_eui64_t *);
481 if (arg)
482 {
483 memcpy(arg, data_in, sizeof(spinel_eui64_t));
484 }
485 }
486 else
487 {
488 const spinel_eui64_t **arg_ptr = va_arg(args->obj, const spinel_eui64_t **);
489 if (arg_ptr)
490 {
491 *arg_ptr = (const spinel_eui64_t *)data_in;
492 }
493 }
494
495 ret += sizeof(spinel_eui64_t);
496 data_in += sizeof(spinel_eui64_t);
497 data_len -= sizeof(spinel_eui64_t);
498 break;
499 }
500
501 case SPINEL_DATATYPE_EUI48_C:
502 {
503 require_action(data_len >= sizeof(spinel_eui48_t), bail, (ret = -1, errno = EOVERFLOW));
504
505 if (in_place)
506 {
507 spinel_eui48_t *arg = va_arg(args->obj, spinel_eui48_t *);
508 if (arg)
509 {
510 memcpy(arg, data_in, sizeof(spinel_eui48_t));
511 }
512 }
513 else
514 {
515 const spinel_eui48_t **arg_ptr = va_arg(args->obj, const spinel_eui48_t **);
516 if (arg_ptr)
517 {
518 *arg_ptr = (const spinel_eui48_t *)data_in;
519 }
520 }
521
522 ret += sizeof(spinel_eui48_t);
523 data_in += sizeof(spinel_eui48_t);
524 data_len -= sizeof(spinel_eui48_t);
525 break;
526 }
527
528 case SPINEL_DATATYPE_UINT_PACKED_C:
529 {
530 unsigned int *arg_ptr = va_arg(args->obj, unsigned int *);
531 spinel_ssize_t pui_len = spinel_packed_uint_decode(data_in, data_len, arg_ptr);
532
533 // Range check
534 require_action(NULL == arg_ptr || (*arg_ptr < SPINEL_MAX_UINT_PACKED), bail, (ret = -1, errno = ERANGE));
535
536 require(pui_len > 0, bail);
537
538 require(pui_len <= (spinel_ssize_t)data_len, bail);
539
540 ret += pui_len;
541 data_in += pui_len;
542 data_len -= (spinel_size_t)pui_len;
543 break;
544 }
545
546 case SPINEL_DATATYPE_UTF8_C:
547 {
548 size_t len;
549
550 // Make sure we have at least one byte.
551 require_action(data_len > 0, bail, (ret = -1, errno = EOVERFLOW));
552
553 // Add 1 for zero termination. If not zero terminated,
554 // len will then be data_len+1, which we will detect
555 // in the next check.
556 len = spinel_strnlen((const char *)data_in, data_len) + 1;
557
558 // Verify that the string is zero terminated.
559 require_action(len <= data_len, bail, (ret = -1, errno = EOVERFLOW));
560
561 // Verify the string follows valid UTF8 encoding.
562 require_action(spinel_validate_utf8(data_in), bail, (ret = -1, errno = EINVAL));
563
564 if (in_place)
565 {
566 char *arg = va_arg(args->obj, char *);
567 size_t len_arg = va_arg(args->obj, size_t);
568 if (arg)
569 {
570 require_action(len_arg >= len, bail, (ret = -1, errno = ENOMEM));
571 memcpy(arg, data_in, len);
572 }
573 }
574 else
575 {
576 const char **arg_ptr = va_arg(args->obj, const char **);
577 if (arg_ptr)
578 {
579 *arg_ptr = (const char *)data_in;
580 }
581 }
582
583 ret += (spinel_size_t)len;
584 data_in += len;
585 data_len -= (spinel_size_t)len;
586 break;
587 }
588
589 case SPINEL_DATATYPE_DATA_C:
590 case SPINEL_DATATYPE_DATA_WLEN_C:
591 {
592 spinel_ssize_t pui_len = 0;
593 uint16_t block_len = 0;
594 const uint8_t *block_ptr = data_in;
595 void *arg_ptr = va_arg(args->obj, void *);
596 unsigned int *block_len_ptr = va_arg(args->obj, unsigned int *);
597 char nextformat = *spinel_next_packed_datatype(pack_format);
598
599 if ((pack_format[0] == SPINEL_DATATYPE_DATA_WLEN_C) || ((nextformat != 0) && (nextformat != ')')))
600 {
601 pui_len = spinel_datatype_unpack(data_in, data_len, SPINEL_DATATYPE_UINT16_S, &block_len);
602 block_ptr += pui_len;
603
604 require(pui_len > 0, bail);
605 require(block_len < SPINEL_FRAME_MAX_SIZE, bail);
606 }
607 else
608 {
609 block_len = (uint16_t)data_len;
610 pui_len = 0;
611 }
612
613 require_action((spinel_ssize_t)data_len >= (block_len + pui_len), bail, (ret = -1, errno = EOVERFLOW));
614
615 if (in_place)
616 {
617 require_action(NULL != block_len_ptr && *block_len_ptr >= block_len, bail, (ret = -1, errno = EINVAL));
618 memcpy(arg_ptr, block_ptr, block_len);
619 }
620 else
621 {
622 const uint8_t **block_ptr_ptr = (const uint8_t **)arg_ptr;
623 if (NULL != block_ptr_ptr)
624 {
625 *block_ptr_ptr = block_ptr;
626 }
627 }
628
629 if (NULL != block_len_ptr)
630 {
631 *block_len_ptr = block_len;
632 }
633
634 block_len += (uint16_t)pui_len;
635 ret += block_len;
636 data_in += block_len;
637 data_len -= block_len;
638 break;
639 }
640
641 case 'T':
642 case SPINEL_DATATYPE_STRUCT_C:
643 {
644 spinel_ssize_t pui_len = 0;
645 uint16_t block_len = 0;
646 spinel_ssize_t actual_len = 0;
647 const uint8_t *block_ptr = data_in;
648 char nextformat = *spinel_next_packed_datatype(pack_format);
649
650 if ((pack_format[0] == SPINEL_DATATYPE_STRUCT_C) || ((nextformat != 0) && (nextformat != ')')))
651 {
652 pui_len = spinel_datatype_unpack(data_in, data_len, SPINEL_DATATYPE_UINT16_S, &block_len);
653 block_ptr += pui_len;
654
655 require(pui_len > 0, bail);
656 require(block_len < SPINEL_FRAME_MAX_SIZE, bail);
657 }
658 else
659 {
660 block_len = (uint16_t)data_len;
661 pui_len = 0;
662 }
663
664 require_action((spinel_ssize_t)data_len >= (block_len + pui_len), bail, (ret = -1, errno = EOVERFLOW));
665
666 actual_len = spinel_datatype_vunpack_(false, block_ptr, block_len, pack_format + 2, args);
667
668 require_action(actual_len > -1, bail, (ret = -1, errno = EOVERFLOW));
669
670 if (pui_len)
671 {
672 block_len += (uint16_t)pui_len;
673 }
674 else
675 {
676 block_len = (uint16_t)actual_len;
677 }
678
679 ret += block_len;
680 data_in += block_len;
681 data_len -= block_len;
682 break;
683 }
684
685 case '.':
686 // Skip.
687 break;
688
689 case SPINEL_DATATYPE_ARRAY_C:
690 default:
691 // Unsupported Type!
692 ret = -1;
693 errno = EINVAL;
694 goto bail;
695 }
696 }
697
698 return ret;
699
700 bail:
701 return ret;
702 }
703
spinel_datatype_unpack_in_place(const uint8_t * data_in,spinel_size_t data_len,const char * pack_format,...)704 spinel_ssize_t spinel_datatype_unpack_in_place(const uint8_t *data_in,
705 spinel_size_t data_len,
706 const char *pack_format,
707 ...)
708 {
709 spinel_ssize_t ret;
710 va_list_obj args;
711 va_start(args.obj, pack_format);
712
713 ret = spinel_datatype_vunpack_(true, data_in, data_len, pack_format, &args);
714
715 va_end(args.obj);
716 return ret;
717 }
718
spinel_datatype_unpack(const uint8_t * data_in,spinel_size_t data_len,const char * pack_format,...)719 spinel_ssize_t spinel_datatype_unpack(const uint8_t *data_in, spinel_size_t data_len, const char *pack_format, ...)
720 {
721 spinel_ssize_t ret;
722 va_list_obj args;
723 va_start(args.obj, pack_format);
724
725 ret = spinel_datatype_vunpack_(false, data_in, data_len, pack_format, &args);
726
727 va_end(args.obj);
728 return ret;
729 }
730
spinel_datatype_vunpack_in_place(const uint8_t * data_in,spinel_size_t data_len,const char * pack_format,va_list args)731 spinel_ssize_t spinel_datatype_vunpack_in_place(const uint8_t *data_in,
732 spinel_size_t data_len,
733 const char *pack_format,
734 va_list args)
735 {
736 spinel_ssize_t ret;
737 va_list_obj args_obj;
738 va_copy(args_obj.obj, args);
739
740 ret = spinel_datatype_vunpack_(true, data_in, data_len, pack_format, &args_obj);
741
742 va_end(args_obj.obj);
743 return ret;
744 }
745
spinel_datatype_vunpack(const uint8_t * data_in,spinel_size_t data_len,const char * pack_format,va_list args)746 spinel_ssize_t spinel_datatype_vunpack(const uint8_t *data_in,
747 spinel_size_t data_len,
748 const char *pack_format,
749 va_list args)
750 {
751 spinel_ssize_t ret;
752 va_list_obj args_obj;
753 va_copy(args_obj.obj, args);
754
755 ret = spinel_datatype_vunpack_(false, data_in, data_len, pack_format, &args_obj);
756
757 va_end(args_obj.obj);
758 return ret;
759 }
760
spinel_datatype_vpack_(uint8_t * data_out,spinel_size_t data_len_max,const char * pack_format,va_list_obj * args)761 static spinel_ssize_t spinel_datatype_vpack_(uint8_t *data_out,
762 spinel_size_t data_len_max,
763 const char *pack_format,
764 va_list_obj *args)
765 {
766 spinel_ssize_t ret = 0;
767
768 // Buffer length sanity check
769 require_action(data_len_max <= SPINEL_MAX_PACK_LENGTH, bail, (ret = -1, errno = EINVAL));
770
771 if (data_out == NULL)
772 {
773 data_len_max = 0;
774 }
775
776 for (; *pack_format != 0; pack_format = spinel_next_packed_datatype(pack_format))
777 {
778 if (*pack_format == ')')
779 {
780 // Don't go past the end of a struct.
781 break;
782 }
783
784 switch ((spinel_datatype_t)*pack_format)
785 {
786 case SPINEL_DATATYPE_BOOL_C:
787 {
788 bool arg = (bool)va_arg(args->obj, int);
789 ret += sizeof(uint8_t);
790
791 if (data_len_max >= sizeof(uint8_t))
792 {
793 data_out[0] = (arg != false);
794 data_out += sizeof(uint8_t);
795 data_len_max -= sizeof(uint8_t);
796 }
797 else
798 {
799 data_len_max = 0;
800 }
801
802 break;
803 }
804
805 case SPINEL_DATATYPE_INT8_C:
806 case SPINEL_DATATYPE_UINT8_C:
807 {
808 uint8_t arg = (uint8_t)va_arg(args->obj, int);
809 ret += sizeof(uint8_t);
810
811 if (data_len_max >= sizeof(uint8_t))
812 {
813 data_out[0] = arg;
814 data_out += sizeof(uint8_t);
815 data_len_max -= sizeof(uint8_t);
816 }
817 else
818 {
819 data_len_max = 0;
820 }
821
822 break;
823 }
824
825 case SPINEL_DATATYPE_INT16_C:
826 case SPINEL_DATATYPE_UINT16_C:
827 {
828 uint16_t arg = (uint16_t)va_arg(args->obj, int);
829 ret += sizeof(uint16_t);
830
831 if (data_len_max >= sizeof(uint16_t))
832 {
833 data_out[1] = (arg >> 8) & 0xff;
834 data_out[0] = (arg >> 0) & 0xff;
835 data_out += sizeof(uint16_t);
836 data_len_max -= sizeof(uint16_t);
837 }
838 else
839 {
840 data_len_max = 0;
841 }
842
843 break;
844 }
845
846 case SPINEL_DATATYPE_INT32_C:
847 case SPINEL_DATATYPE_UINT32_C:
848 {
849 uint32_t arg = (uint32_t)va_arg(args->obj, int);
850 ret += sizeof(uint32_t);
851
852 if (data_len_max >= sizeof(uint32_t))
853 {
854 data_out[3] = (arg >> 24) & 0xff;
855 data_out[2] = (arg >> 16) & 0xff;
856 data_out[1] = (arg >> 8) & 0xff;
857 data_out[0] = (arg >> 0) & 0xff;
858 data_out += sizeof(uint32_t);
859 data_len_max -= sizeof(uint32_t);
860 }
861 else
862 {
863 data_len_max = 0;
864 }
865
866 break;
867 }
868
869 case SPINEL_DATATYPE_INT64_C:
870 case SPINEL_DATATYPE_UINT64_C:
871 {
872 uint64_t arg = va_arg(args->obj, uint64_t);
873
874 ret += sizeof(uint64_t);
875
876 if (data_len_max >= sizeof(uint64_t))
877 {
878 data_out[7] = (arg >> 56) & 0xff;
879 data_out[6] = (arg >> 48) & 0xff;
880 data_out[5] = (arg >> 40) & 0xff;
881 data_out[4] = (arg >> 32) & 0xff;
882 data_out[3] = (arg >> 24) & 0xff;
883 data_out[2] = (arg >> 16) & 0xff;
884 data_out[1] = (arg >> 8) & 0xff;
885 data_out[0] = (arg >> 0) & 0xff;
886 data_out += sizeof(uint64_t);
887 data_len_max -= sizeof(uint64_t);
888 }
889 else
890 {
891 data_len_max = 0;
892 }
893
894 break;
895 }
896
897 case SPINEL_DATATYPE_IPv6ADDR_C:
898 {
899 spinel_ipv6addr_t *arg = va_arg(args->obj, spinel_ipv6addr_t *);
900 ret += sizeof(spinel_ipv6addr_t);
901
902 if (data_len_max >= sizeof(spinel_ipv6addr_t))
903 {
904 *(spinel_ipv6addr_t *)data_out = *arg;
905 data_out += sizeof(spinel_ipv6addr_t);
906 data_len_max -= sizeof(spinel_ipv6addr_t);
907 }
908 else
909 {
910 data_len_max = 0;
911 }
912
913 break;
914 }
915
916 case SPINEL_DATATYPE_EUI48_C:
917 {
918 spinel_eui48_t *arg = va_arg(args->obj, spinel_eui48_t *);
919 ret += sizeof(spinel_eui48_t);
920
921 if (data_len_max >= sizeof(spinel_eui48_t))
922 {
923 *(spinel_eui48_t *)data_out = *arg;
924 data_out += sizeof(spinel_eui48_t);
925 data_len_max -= sizeof(spinel_eui48_t);
926 }
927 else
928 {
929 data_len_max = 0;
930 }
931
932 break;
933 }
934
935 case SPINEL_DATATYPE_EUI64_C:
936 {
937 spinel_eui64_t *arg = va_arg(args->obj, spinel_eui64_t *);
938 ret += sizeof(spinel_eui64_t);
939
940 if (data_len_max >= sizeof(spinel_eui64_t))
941 {
942 *(spinel_eui64_t *)data_out = *arg;
943 data_out += sizeof(spinel_eui64_t);
944 data_len_max -= sizeof(spinel_eui64_t);
945 }
946 else
947 {
948 data_len_max = 0;
949 }
950
951 break;
952 }
953
954 case SPINEL_DATATYPE_UINT_PACKED_C:
955 {
956 uint32_t arg = va_arg(args->obj, uint32_t);
957 spinel_ssize_t encoded_size;
958
959 // Range Check
960 require_action(arg < SPINEL_MAX_UINT_PACKED, bail, {
961 ret = -1;
962 errno = EINVAL;
963 });
964
965 encoded_size = spinel_packed_uint_encode(data_out, data_len_max, arg);
966 ret += encoded_size;
967
968 if ((spinel_ssize_t)data_len_max >= encoded_size)
969 {
970 data_out += encoded_size;
971 data_len_max -= (spinel_size_t)encoded_size;
972 }
973 else
974 {
975 data_len_max = 0;
976 }
977
978 break;
979 }
980
981 case SPINEL_DATATYPE_UTF8_C:
982 {
983 const char *string_arg = va_arg(args->obj, const char *);
984 size_t string_arg_len = 0;
985
986 if (string_arg)
987 {
988 string_arg_len = strlen(string_arg) + 1;
989 }
990 else
991 {
992 string_arg = "";
993 string_arg_len = 1;
994 }
995
996 ret += (spinel_size_t)string_arg_len;
997
998 if (data_len_max >= string_arg_len)
999 {
1000 memcpy(data_out, string_arg, string_arg_len);
1001
1002 data_out += string_arg_len;
1003 data_len_max -= (spinel_size_t)string_arg_len;
1004 }
1005 else
1006 {
1007 data_len_max = 0;
1008 }
1009
1010 break;
1011 }
1012
1013 case SPINEL_DATATYPE_DATA_WLEN_C:
1014 case SPINEL_DATATYPE_DATA_C:
1015 {
1016 const uint8_t *arg = va_arg(args->obj, const uint8_t *);
1017 uint32_t data_size_arg = va_arg(args->obj, uint32_t);
1018 spinel_ssize_t size_len = 0;
1019 char nextformat = *spinel_next_packed_datatype(pack_format);
1020
1021 if ((pack_format[0] == SPINEL_DATATYPE_DATA_WLEN_C) || ((nextformat != 0) && (nextformat != ')')))
1022 {
1023 size_len = spinel_datatype_pack(data_out, data_len_max, SPINEL_DATATYPE_UINT16_S, data_size_arg);
1024 require_action(size_len > 0, bail, {
1025 ret = -1;
1026 errno = EINVAL;
1027 });
1028 }
1029
1030 ret += (spinel_size_t)size_len + data_size_arg;
1031
1032 if (data_len_max >= (spinel_size_t)size_len + data_size_arg)
1033 {
1034 data_out += size_len;
1035 data_len_max -= (spinel_size_t)size_len;
1036
1037 if (data_out && arg)
1038 {
1039 memcpy(data_out, arg, data_size_arg);
1040 }
1041
1042 data_out += data_size_arg;
1043 data_len_max -= data_size_arg;
1044 }
1045 else
1046 {
1047 data_len_max = 0;
1048 }
1049
1050 break;
1051 }
1052
1053 case 'T':
1054 case SPINEL_DATATYPE_STRUCT_C:
1055 {
1056 spinel_ssize_t struct_len = 0;
1057 spinel_ssize_t size_len = 0;
1058 char nextformat = *spinel_next_packed_datatype(pack_format);
1059
1060 require_action(pack_format[1] == '(', bail, {
1061 ret = -1;
1062 errno = EINVAL;
1063 });
1064
1065 // First we figure out the size of the struct
1066 {
1067 va_list_obj subargs;
1068 va_copy(subargs.obj, args->obj);
1069 struct_len = spinel_datatype_vpack_(NULL, 0, pack_format + 2, &subargs);
1070 va_end(subargs.obj);
1071 }
1072
1073 if ((pack_format[0] == SPINEL_DATATYPE_STRUCT_C) || ((nextformat != 0) && (nextformat != ')')))
1074 {
1075 size_len = spinel_datatype_pack(data_out, data_len_max, SPINEL_DATATYPE_UINT16_S, struct_len);
1076 require_action(size_len > 0, bail, {
1077 ret = -1;
1078 errno = EINVAL;
1079 });
1080 }
1081
1082 ret += size_len + struct_len;
1083
1084 if (struct_len + size_len <= (spinel_ssize_t)data_len_max)
1085 {
1086 data_out += size_len;
1087 data_len_max -= (spinel_size_t)size_len;
1088
1089 struct_len = spinel_datatype_vpack_(data_out, data_len_max, pack_format + 2, args);
1090
1091 data_out += struct_len;
1092 data_len_max -= (spinel_size_t)struct_len;
1093 }
1094 else
1095 {
1096 data_len_max = 0;
1097 }
1098
1099 break;
1100 }
1101
1102 case '.':
1103 // Skip.
1104 break;
1105
1106 default:
1107 // Unsupported Type!
1108 ret = -1;
1109 errno = EINVAL;
1110 goto bail;
1111 }
1112 }
1113
1114 bail:
1115 return ret;
1116 }
1117
spinel_datatype_pack(uint8_t * data_out,spinel_size_t data_len_max,const char * pack_format,...)1118 spinel_ssize_t spinel_datatype_pack(uint8_t *data_out, spinel_size_t data_len_max, const char *pack_format, ...)
1119 {
1120 int ret;
1121 va_list_obj args;
1122 va_start(args.obj, pack_format);
1123
1124 ret = spinel_datatype_vpack_(data_out, data_len_max, pack_format, &args);
1125
1126 va_end(args.obj);
1127 return ret;
1128 }
1129
spinel_datatype_vpack(uint8_t * data_out,spinel_size_t data_len_max,const char * pack_format,va_list args)1130 spinel_ssize_t spinel_datatype_vpack(uint8_t *data_out,
1131 spinel_size_t data_len_max,
1132 const char *pack_format,
1133 va_list args)
1134 {
1135 int ret;
1136 va_list_obj args_obj;
1137 va_copy(args_obj.obj, args);
1138
1139 ret = spinel_datatype_vpack_(data_out, data_len_max, pack_format, &args_obj);
1140
1141 va_end(args_obj.obj);
1142 return ret;
1143 }
1144
1145 // ----------------------------------------------------------------------------
1146 // MARK: -
1147
1148 // LCOV_EXCL_START
1149
1150 struct spinel_cstr
1151 {
1152 uint32_t val;
1153 const char *str;
1154 };
1155
spinel_to_cstr(const struct spinel_cstr * table,uint32_t val)1156 static const char *spinel_to_cstr(const struct spinel_cstr *table, uint32_t val)
1157 {
1158 int i;
1159
1160 for (i = 0; table[i].str; i++)
1161 if (val == table[i].val)
1162 return table[i].str;
1163 return "UNKNOWN";
1164 }
1165
spinel_command_to_cstr(spinel_command_t command)1166 const char *spinel_command_to_cstr(spinel_command_t command)
1167 {
1168 static const struct spinel_cstr spinel_commands_cstr[] = {
1169 {SPINEL_CMD_NOOP, "NOOP"},
1170 {SPINEL_CMD_RESET, "RESET"},
1171 {SPINEL_CMD_PROP_VALUE_GET, "PROP_VALUE_GET"},
1172 {SPINEL_CMD_PROP_VALUE_SET, "PROP_VALUE_SET"},
1173 {SPINEL_CMD_PROP_VALUE_INSERT, "PROP_VALUE_INSERT"},
1174 {SPINEL_CMD_PROP_VALUE_REMOVE, "PROP_VALUE_REMOVE"},
1175 {SPINEL_CMD_PROP_VALUE_IS, "PROP_VALUE_IS"},
1176 {SPINEL_CMD_PROP_VALUE_INSERTED, "PROP_VALUE_INSERTED"},
1177 {SPINEL_CMD_PROP_VALUE_REMOVED, "PROP_VALUE_REMOVED"},
1178 {SPINEL_CMD_NET_SAVE, "NET_SAVE"},
1179 {SPINEL_CMD_NET_CLEAR, "NET_CLEAR"},
1180 {SPINEL_CMD_NET_RECALL, "NET_RECALL"},
1181 {SPINEL_CMD_HBO_OFFLOAD, "HBO_OFFLOAD"},
1182 {SPINEL_CMD_HBO_RECLAIM, "HBO_RECLAIM"},
1183 {SPINEL_CMD_HBO_DROP, "HBO_DROP"},
1184 {SPINEL_CMD_HBO_OFFLOADED, "HBO_OFFLOADED"},
1185 {SPINEL_CMD_HBO_RECLAIMED, "HBO_RECLAIMED"},
1186 {SPINEL_CMD_HBO_DROPPED, "HBO_DROPPED"},
1187 {SPINEL_CMD_PEEK, "PEEK"},
1188 {SPINEL_CMD_PEEK_RET, "PEEK_RET"},
1189 {SPINEL_CMD_POKE, "POKE"},
1190 {SPINEL_CMD_PROP_VALUE_MULTI_GET, "PROP_VALUE_MULTI_GET"},
1191 {SPINEL_CMD_PROP_VALUE_MULTI_SET, "PROP_VALUE_MULTI_SET"},
1192 {SPINEL_CMD_PROP_VALUES_ARE, "PROP_VALUES_ARE"},
1193 {0, NULL},
1194 };
1195
1196 return spinel_to_cstr(spinel_commands_cstr, command);
1197 }
1198
spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)1199 const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
1200 {
1201 static const struct spinel_cstr spinel_prop_cstr[] = {
1202 {SPINEL_PROP_LAST_STATUS, "LAST_STATUS"},
1203 {SPINEL_PROP_PROTOCOL_VERSION, "PROTOCOL_VERSION"},
1204 {SPINEL_PROP_NCP_VERSION, "NCP_VERSION"},
1205 {SPINEL_PROP_INTERFACE_TYPE, "INTERFACE_TYPE"},
1206 {SPINEL_PROP_VENDOR_ID, "VENDOR_ID"},
1207 {SPINEL_PROP_CAPS, "CAPS"},
1208 {SPINEL_PROP_INTERFACE_COUNT, "INTERFACE_COUNT"},
1209 {SPINEL_PROP_POWER_STATE, "POWER_STATE"},
1210 {SPINEL_PROP_HWADDR, "HWADDR"},
1211 {SPINEL_PROP_LOCK, "LOCK"},
1212 {SPINEL_PROP_HBO_MEM_MAX, "HBO_MEM_MAX"},
1213 {SPINEL_PROP_HBO_BLOCK_MAX, "HBO_BLOCK_MAX"},
1214 {SPINEL_PROP_HOST_POWER_STATE, "HOST_POWER_STATE"},
1215 {SPINEL_PROP_MCU_POWER_STATE, "MCU_POWER_STATE"},
1216 {SPINEL_PROP_GPIO_CONFIG, "GPIO_CONFIG"},
1217 {SPINEL_PROP_GPIO_STATE, "GPIO_STATE"},
1218 {SPINEL_PROP_GPIO_STATE_SET, "GPIO_STATE_SET"},
1219 {SPINEL_PROP_GPIO_STATE_CLEAR, "GPIO_STATE_CLEAR"},
1220 {SPINEL_PROP_TRNG_32, "TRNG_32"},
1221 {SPINEL_PROP_TRNG_128, "TRNG_128"},
1222 {SPINEL_PROP_TRNG_RAW_32, "TRNG_RAW_32"},
1223 {SPINEL_PROP_UNSOL_UPDATE_FILTER, "UNSOL_UPDATE_FILTER"},
1224 {SPINEL_PROP_UNSOL_UPDATE_LIST, "UNSOL_UPDATE_LIST"},
1225 {SPINEL_PROP_PHY_ENABLED, "PHY_ENABLED"},
1226 {SPINEL_PROP_PHY_CHAN, "PHY_CHAN"},
1227 {SPINEL_PROP_PHY_CHAN_SUPPORTED, "PHY_CHAN_SUPPORTED"},
1228 {SPINEL_PROP_PHY_FREQ, "PHY_FREQ"},
1229 {SPINEL_PROP_PHY_CCA_THRESHOLD, "PHY_CCA_THRESHOLD"},
1230 {SPINEL_PROP_PHY_TX_POWER, "PHY_TX_POWER"},
1231 {SPINEL_PROP_PHY_FEM_LNA_GAIN, "PHY_FEM_LNA_GAIN"},
1232 {SPINEL_PROP_PHY_RSSI, "PHY_RSSI"},
1233 {SPINEL_PROP_PHY_RX_SENSITIVITY, "PHY_RX_SENSITIVITY"},
1234 {SPINEL_PROP_PHY_PCAP_ENABLED, "PHY_PCAP_ENABLED"},
1235 {SPINEL_PROP_PHY_CHAN_PREFERRED, "PHY_CHAN_PREFERRED"},
1236 {SPINEL_PROP_PHY_CHAN_MAX_POWER, "PHY_CHAN_MAX_POWER"},
1237 {SPINEL_PROP_PHY_REGION_CODE, "PHY_REGION_CODE"},
1238 {SPINEL_PROP_PHY_CALIBRATED_POWER, "PHY_CALIBRATED_POWER"},
1239 {SPINEL_PROP_PHY_CHAN_TARGET_POWER, "PHY_CHAN_TARGET_POWER"},
1240 {SPINEL_PROP_JAM_DETECT_ENABLE, "JAM_DETECT_ENABLE"},
1241 {SPINEL_PROP_JAM_DETECTED, "JAM_DETECTED"},
1242 {SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD, "JAM_DETECT_RSSI_THRESHOLD"},
1243 {SPINEL_PROP_JAM_DETECT_WINDOW, "JAM_DETECT_WINDOW"},
1244 {SPINEL_PROP_JAM_DETECT_BUSY, "JAM_DETECT_BUSY"},
1245 {SPINEL_PROP_JAM_DETECT_HISTORY_BITMAP, "JAM_DETECT_HISTORY_BITMAP"},
1246 {SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_INTERVAL, "CHANNEL_MONITOR_SAMPLE_INTERVAL"},
1247 {SPINEL_PROP_CHANNEL_MONITOR_RSSI_THRESHOLD, "CHANNEL_MONITOR_RSSI_THRESHOLD"},
1248 {SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_WINDOW, "CHANNEL_MONITOR_SAMPLE_WINDOW"},
1249 {SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_COUNT, "CHANNEL_MONITOR_SAMPLE_COUNT"},
1250 {SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_OCCUPANCY, "CHANNEL_MONITOR_CHANNEL_OCCUPANCY"},
1251 {SPINEL_PROP_RADIO_CAPS, "RADIO_CAPS"},
1252 {SPINEL_PROP_RADIO_COEX_METRICS, "RADIO_COEX_METRICS"},
1253 {SPINEL_PROP_RADIO_COEX_ENABLE, "RADIO_COEX_ENABLE"},
1254 {SPINEL_PROP_MAC_SCAN_STATE, "MAC_SCAN_STATE"},
1255 {SPINEL_PROP_MAC_SCAN_MASK, "MAC_SCAN_MASK"},
1256 {SPINEL_PROP_MAC_SCAN_PERIOD, "MAC_SCAN_PERIOD"},
1257 {SPINEL_PROP_MAC_SCAN_BEACON, "MAC_SCAN_BEACON"},
1258 {SPINEL_PROP_MAC_15_4_LADDR, "MAC_15_4_LADDR"},
1259 {SPINEL_PROP_MAC_15_4_SADDR, "MAC_15_4_SADDR"},
1260 {SPINEL_PROP_MAC_15_4_PANID, "MAC_15_4_PANID"},
1261 {SPINEL_PROP_MAC_RAW_STREAM_ENABLED, "MAC_RAW_STREAM_ENABLED"},
1262 {SPINEL_PROP_MAC_PROMISCUOUS_MODE, "MAC_PROMISCUOUS_MODE"},
1263 {SPINEL_PROP_MAC_ENERGY_SCAN_RESULT, "MAC_ENERGY_SCAN_RESULT"},
1264 {SPINEL_PROP_MAC_DATA_POLL_PERIOD, "MAC_DATA_POLL_PERIOD"},
1265 {SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE, "MAC_RX_ON_WHEN_IDLE_MODE"},
1266 {SPINEL_PROP_MAC_ALLOWLIST, "MAC_ALLOWLIST"},
1267 {SPINEL_PROP_MAC_ALLOWLIST_ENABLED, "MAC_ALLOWLIST_ENABLED"},
1268 {SPINEL_PROP_MAC_EXTENDED_ADDR, "MAC_EXTENDED_ADDR"},
1269 {SPINEL_PROP_MAC_SRC_MATCH_ENABLED, "MAC_SRC_MATCH_ENABLED"},
1270 {SPINEL_PROP_MAC_SRC_MATCH_SHORT_ADDRESSES, "MAC_SRC_MATCH_SHORT_ADDRESSES"},
1271 {SPINEL_PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES, "MAC_SRC_MATCH_EXTENDED_ADDRESSES"},
1272 {SPINEL_PROP_MAC_DENYLIST, "MAC_DENYLIST"},
1273 {SPINEL_PROP_MAC_DENYLIST_ENABLED, "MAC_DENYLIST_ENABLED"},
1274 {SPINEL_PROP_MAC_FIXED_RSS, "MAC_FIXED_RSS"},
1275 {SPINEL_PROP_MAC_CCA_FAILURE_RATE, "MAC_CCA_FAILURE_RATE"},
1276 {SPINEL_PROP_MAC_MAX_RETRY_NUMBER_DIRECT, "MAC_MAX_RETRY_NUMBER_DIRECT"},
1277 {SPINEL_PROP_MAC_MAX_RETRY_NUMBER_INDIRECT, "MAC_MAX_RETRY_NUMBER_INDIRECT"},
1278 {SPINEL_PROP_NET_SAVED, "NET_SAVED"},
1279 {SPINEL_PROP_NET_IF_UP, "NET_IF_UP"},
1280 {SPINEL_PROP_NET_STACK_UP, "NET_STACK_UP"},
1281 {SPINEL_PROP_NET_ROLE, "NET_ROLE"},
1282 {SPINEL_PROP_NET_NETWORK_NAME, "NET_NETWORK_NAME"},
1283 {SPINEL_PROP_NET_XPANID, "NET_XPANID"},
1284 {SPINEL_PROP_NET_NETWORK_KEY, "NET_NETWORK_KEY"},
1285 {SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER, "NET_KEY_SEQUENCE_COUNTER"},
1286 {SPINEL_PROP_NET_PARTITION_ID, "NET_PARTITION_ID"},
1287 {SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING, "NET_REQUIRE_JOIN_EXISTING"},
1288 {SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME, "NET_KEY_SWITCH_GUARDTIME"},
1289 {SPINEL_PROP_NET_PSKC, "NET_PSKC"},
1290 {SPINEL_PROP_NET_LEAVE_GRACEFULLY, "NET_LEAVE_GRACEFULLY"},
1291 {SPINEL_PROP_THREAD_LEADER_ADDR, "THREAD_LEADER_ADDR"},
1292 {SPINEL_PROP_THREAD_PARENT, "THREAD_PARENT"},
1293 {SPINEL_PROP_THREAD_CHILD_TABLE, "THREAD_CHILD_TABLE"},
1294 {SPINEL_PROP_THREAD_LEADER_RID, "THREAD_LEADER_RID"},
1295 {SPINEL_PROP_THREAD_LEADER_WEIGHT, "THREAD_LEADER_WEIGHT"},
1296 {SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT, "THREAD_LOCAL_LEADER_WEIGHT"},
1297 {SPINEL_PROP_THREAD_NETWORK_DATA, "THREAD_NETWORK_DATA"},
1298 {SPINEL_PROP_THREAD_NETWORK_DATA_VERSION, "THREAD_NETWORK_DATA_VERSION"},
1299 {SPINEL_PROP_THREAD_STABLE_NETWORK_DATA, "THREAD_STABLE_NETWORK_DATA"},
1300 {SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION, "THREAD_STABLE_NETWORK_DATA_VERSION"},
1301 {SPINEL_PROP_THREAD_ON_MESH_NETS, "THREAD_ON_MESH_NETS"},
1302 {SPINEL_PROP_THREAD_OFF_MESH_ROUTES, "THREAD_OFF_MESH_ROUTES"},
1303 {SPINEL_PROP_THREAD_ASSISTING_PORTS, "THREAD_ASSISTING_PORTS"},
1304 {SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE, "THREAD_ALLOW_LOCAL_NET_DATA_CHANGE"},
1305 {SPINEL_PROP_THREAD_MODE, "THREAD_MODE"},
1306 {SPINEL_PROP_THREAD_CHILD_TIMEOUT, "THREAD_CHILD_TIMEOUT"},
1307 {SPINEL_PROP_THREAD_RLOC16, "THREAD_RLOC16"},
1308 {SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD, "THREAD_ROUTER_UPGRADE_THRESHOLD"},
1309 {SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY, "THREAD_CONTEXT_REUSE_DELAY"},
1310 {SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT, "THREAD_NETWORK_ID_TIMEOUT"},
1311 {SPINEL_PROP_THREAD_ACTIVE_ROUTER_IDS, "THREAD_ACTIVE_ROUTER_IDS"},
1312 {SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU, "THREAD_RLOC16_DEBUG_PASSTHRU"},
1313 {SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED, "THREAD_ROUTER_ROLE_ENABLED"},
1314 {SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD, "THREAD_ROUTER_DOWNGRADE_THRESHOLD"},
1315 {SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER, "THREAD_ROUTER_SELECTION_JITTER"},
1316 {SPINEL_PROP_THREAD_PREFERRED_ROUTER_ID, "THREAD_PREFERRED_ROUTER_ID"},
1317 {SPINEL_PROP_THREAD_NEIGHBOR_TABLE, "THREAD_NEIGHBOR_TABLE"},
1318 {SPINEL_PROP_THREAD_CHILD_COUNT_MAX, "THREAD_CHILD_COUNT_MAX"},
1319 {SPINEL_PROP_THREAD_LEADER_NETWORK_DATA, "THREAD_LEADER_NETWORK_DATA"},
1320 {SPINEL_PROP_THREAD_STABLE_LEADER_NETWORK_DATA, "THREAD_STABLE_LEADER_NETWORK_DATA"},
1321 {SPINEL_PROP_THREAD_JOINERS, "THREAD_JOINERS"},
1322 {SPINEL_PROP_THREAD_COMMISSIONER_ENABLED, "THREAD_COMMISSIONER_ENABLED"},
1323 {SPINEL_PROP_THREAD_TMF_PROXY_ENABLED, "THREAD_TMF_PROXY_ENABLED"},
1324 {SPINEL_PROP_THREAD_TMF_PROXY_STREAM, "THREAD_TMF_PROXY_STREAM"},
1325 {SPINEL_PROP_THREAD_UDP_FORWARD_STREAM, "THREAD_UDP_FORWARD_STREAM"},
1326 {SPINEL_PROP_THREAD_DISCOVERY_SCAN_JOINER_FLAG, "THREAD_DISCOVERY_SCAN_JOINER_FLAG"},
1327 {SPINEL_PROP_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING, "THREAD_DISCOVERY_SCAN_ENABLE_FILTERING"},
1328 {SPINEL_PROP_THREAD_DISCOVERY_SCAN_PANID, "THREAD_DISCOVERY_SCAN_PANID"},
1329 {SPINEL_PROP_THREAD_STEERING_DATA, "THREAD_STEERING_DATA"},
1330 {SPINEL_PROP_THREAD_ROUTER_TABLE, "THREAD_ROUTER_TABLE"},
1331 {SPINEL_PROP_THREAD_ACTIVE_DATASET, "THREAD_ACTIVE_DATASET"},
1332 {SPINEL_PROP_THREAD_PENDING_DATASET, "THREAD_PENDING_DATASET"},
1333 {SPINEL_PROP_THREAD_MGMT_SET_ACTIVE_DATASET, "THREAD_MGMT_SET_ACTIVE_DATASET"},
1334 {SPINEL_PROP_THREAD_MGMT_SET_PENDING_DATASET, "THREAD_MGMT_SET_PENDING_DATASET"},
1335 {SPINEL_PROP_DATASET_ACTIVE_TIMESTAMP, "DATASET_ACTIVE_TIMESTAMP"},
1336 {SPINEL_PROP_DATASET_PENDING_TIMESTAMP, "DATASET_PENDING_TIMESTAMP"},
1337 {SPINEL_PROP_DATASET_DELAY_TIMER, "DATASET_DELAY_TIMER"},
1338 {SPINEL_PROP_DATASET_SECURITY_POLICY, "DATASET_SECURITY_POLICY"},
1339 {SPINEL_PROP_DATASET_RAW_TLVS, "DATASET_RAW_TLVS"},
1340 {SPINEL_PROP_THREAD_CHILD_TABLE_ADDRESSES, "THREAD_CHILD_TABLE_ADDRESSES"},
1341 {SPINEL_PROP_THREAD_NEIGHBOR_TABLE_ERROR_RATES, "THREAD_NEIGHBOR_TABLE_ERROR_RATES"},
1342 {SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE, "THREAD_ADDRESS_CACHE_TABLE"},
1343 {SPINEL_PROP_THREAD_MGMT_GET_ACTIVE_DATASET, "THREAD_MGMT_GET_ACTIVE_DATASET"},
1344 {SPINEL_PROP_THREAD_MGMT_GET_PENDING_DATASET, "THREAD_MGMT_GET_PENDING_DATASET"},
1345 {SPINEL_PROP_DATASET_DEST_ADDRESS, "DATASET_DEST_ADDRESS"},
1346 {SPINEL_PROP_THREAD_NEW_DATASET, "THREAD_NEW_DATASET"},
1347 {SPINEL_PROP_THREAD_CSL_PERIOD, "THREAD_CSL_PERIOD"},
1348 {SPINEL_PROP_THREAD_CSL_TIMEOUT, "THREAD_CSL_TIMEOUT"},
1349 {SPINEL_PROP_THREAD_CSL_CHANNEL, "THREAD_CSL_CHANNEL"},
1350 {SPINEL_PROP_THREAD_DOMAIN_NAME, "THREAD_DOMAIN_NAME"},
1351 {SPINEL_PROP_THREAD_LINK_METRICS_QUERY, "THREAD_LINK_METRICS_QUERY"},
1352 {SPINEL_PROP_THREAD_LINK_METRICS_QUERY_RESULT, "THREAD_LINK_METRICS_QUERY_RESULT"},
1353 {SPINEL_PROP_THREAD_LINK_METRICS_PROBE, "THREAD_LINK_METRICS_PROBE"},
1354 {SPINEL_PROP_THREAD_LINK_METRICS_MGMT_ENH_ACK, "THREAD_LINK_METRICS_MGMT_ENH_ACK"},
1355 {SPINEL_PROP_THREAD_LINK_METRICS_MGMT_ENH_ACK_IE, "THREAD_LINK_METRICS_MGMT_ENH_ACK_IE"},
1356 {SPINEL_PROP_THREAD_LINK_METRICS_MGMT_FORWARD, "THREAD_LINK_METRICS_MGMT_FORWARD"},
1357 {SPINEL_PROP_THREAD_LINK_METRICS_MGMT_RESPONSE, "THREAD_LINK_METRICS_MGMT_RESPONSE"},
1358 {SPINEL_PROP_THREAD_MLR_REQUEST, "THREAD_MLR_REQUEST"},
1359 {SPINEL_PROP_THREAD_MLR_RESPONSE, "THREAD_MLR_RESPONSE"},
1360 {SPINEL_PROP_THREAD_BACKBONE_ROUTER_PRIMARY, "THREAD_BACKBONE_ROUTER_PRIMARY"},
1361 {SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE, "THREAD_BACKBONE_ROUTER_LOCAL_STATE"},
1362 {SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG, "THREAD_BACKBONE_ROUTER_LOCAL_CONFIG"},
1363 {SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTER, "THREAD_BACKBONE_ROUTER_LOCAL_REGISTER"},
1364 {SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER,
1365 "THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER"},
1366 {SPINEL_PROP_THREAD_MGMT_SET_PENDING_DATASET_TLVS, "THREAD_MGMT_SET_PENDING_DATASET_TLVS"},
1367 {SPINEL_PROP_MESHCOP_JOINER_STATE, "MESHCOP_JOINER_STATE"},
1368 {SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING, "MESHCOP_JOINER_COMMISSIONING"},
1369 {SPINEL_PROP_IPV6_LL_ADDR, "IPV6_LL_ADDR"},
1370 {SPINEL_PROP_IPV6_ML_ADDR, "IPV6_ML_ADDR"},
1371 {SPINEL_PROP_IPV6_ML_PREFIX, "IPV6_ML_PREFIX"},
1372 {SPINEL_PROP_IPV6_ADDRESS_TABLE, "IPV6_ADDRESS_TABLE"},
1373 {SPINEL_PROP_IPV6_ROUTE_TABLE, "IPV6_ROUTE_TABLE"},
1374 {SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD, "IPV6_ICMP_PING_OFFLOAD"},
1375 {SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE, "IPV6_MULTICAST_ADDRESS_TABLE"},
1376 {SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD_MODE, "IPV6_ICMP_PING_OFFLOAD_MODE"},
1377 {SPINEL_PROP_STREAM_DEBUG, "STREAM_DEBUG"},
1378 {SPINEL_PROP_STREAM_RAW, "STREAM_RAW"},
1379 {SPINEL_PROP_STREAM_NET, "STREAM_NET"},
1380 {SPINEL_PROP_STREAM_NET_INSECURE, "STREAM_NET_INSECURE"},
1381 {SPINEL_PROP_STREAM_LOG, "STREAM_LOG"},
1382 {SPINEL_PROP_MESHCOP_COMMISSIONER_STATE, "MESHCOP_COMMISSIONER_STATE"},
1383 {SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS, "MESHCOP_COMMISSIONER_JOINERS"},
1384 {SPINEL_PROP_MESHCOP_COMMISSIONER_PROVISIONING_URL, "MESHCOP_COMMISSIONER_PROVISIONING_URL"},
1385 {SPINEL_PROP_MESHCOP_COMMISSIONER_SESSION_ID, "MESHCOP_COMMISSIONER_SESSION_ID"},
1386 {SPINEL_PROP_MESHCOP_JOINER_DISCERNER, "MESHCOP_JOINER_DISCERNER"},
1387 {SPINEL_PROP_MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN, "MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN"},
1388 {SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN, "MESHCOP_COMMISSIONER_ENERGY_SCAN"},
1389 {SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN_RESULT, "MESHCOP_COMMISSIONER_ENERGY_SCAN_RESULT"},
1390 {SPINEL_PROP_MESHCOP_COMMISSIONER_PAN_ID_QUERY, "MESHCOP_COMMISSIONER_PAN_ID_QUERY"},
1391 {SPINEL_PROP_MESHCOP_COMMISSIONER_PAN_ID_CONFLICT_RESULT, "MESHCOP_COMMISSIONER_PAN_ID_CONFLICT_RESULT"},
1392 {SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_GET, "MESHCOP_COMMISSIONER_MGMT_GET"},
1393 {SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_SET, "MESHCOP_COMMISSIONER_MGMT_SET"},
1394 {SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC, "MESHCOP_COMMISSIONER_GENERATE_PSKC"},
1395 {SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL, "CHANNEL_MANAGER_NEW_CHANNEL"},
1396 {SPINEL_PROP_CHANNEL_MANAGER_DELAY, "CHANNEL_MANAGER_DELAY"},
1397 {SPINEL_PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS, "CHANNEL_MANAGER_SUPPORTED_CHANNELS"},
1398 {SPINEL_PROP_CHANNEL_MANAGER_FAVORED_CHANNELS, "CHANNEL_MANAGER_FAVORED_CHANNELS"},
1399 {SPINEL_PROP_CHANNEL_MANAGER_CHANNEL_SELECT, "CHANNEL_MANAGER_CHANNEL_SELECT"},
1400 {SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_ENABLED, "CHANNEL_MANAGER_AUTO_SELECT_ENABLED"},
1401 {SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_INTERVAL, "CHANNEL_MANAGER_AUTO_SELECT_INTERVAL"},
1402 {SPINEL_PROP_THREAD_NETWORK_TIME, "THREAD_NETWORK_TIME"},
1403 {SPINEL_PROP_TIME_SYNC_PERIOD, "TIME_SYNC_PERIOD"},
1404 {SPINEL_PROP_TIME_SYNC_XTAL_THRESHOLD, "TIME_SYNC_XTAL_THRESHOLD"},
1405 {SPINEL_PROP_CHILD_SUPERVISION_INTERVAL, "CHILD_SUPERVISION_INTERVAL"},
1406 {SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT, "CHILD_SUPERVISION_CHECK_TIMEOUT"},
1407 {SPINEL_PROP_RCP_VERSION, "RCP_VERSION"},
1408 {SPINEL_PROP_RCP_TIMESTAMP, "TIMESTAMP"},
1409 {SPINEL_PROP_RCP_ENH_ACK_PROBING, "ENH_ACK_PROBING"},
1410 {SPINEL_PROP_RCP_CSL_ACCURACY, "CSL_ACCURACY"},
1411 {SPINEL_PROP_RCP_CSL_UNCERTAINTY, "CSL_UNCERTAINTY"},
1412 {SPINEL_PROP_PARENT_RESPONSE_INFO, "PARENT_RESPONSE_INFO"},
1413 {SPINEL_PROP_SLAAC_ENABLED, "SLAAC_ENABLED"},
1414 {SPINEL_PROP_SUPPORTED_RADIO_LINKS, "SUPPORTED_RADIO_LINKS"},
1415 {SPINEL_PROP_NEIGHBOR_TABLE_MULTI_RADIO_INFO, "NEIGHBOR_TABLE_MULTI_RADIO_INFO"},
1416 {SPINEL_PROP_SRP_CLIENT_START, "SRP_CLIENT_START"},
1417 {SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL, "SRP_CLIENT_LEASE_INTERVAL"},
1418 {SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL, "SRP_CLIENT_KEY_LEASE_INTERVAL"},
1419 {SPINEL_PROP_SRP_CLIENT_HOST_INFO, "SRP_CLIENT_HOST_INFO"},
1420 {SPINEL_PROP_SRP_CLIENT_HOST_NAME, "SRP_CLIENT_HOST_NAME"},
1421 {SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES, "SRP_CLIENT_HOST_ADDRESSES"},
1422 {SPINEL_PROP_SRP_CLIENT_SERVICES, "SRP_CLIENT_SERVICES"},
1423 {SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_REMOVE, "SRP_CLIENT_HOST_SERVICES_REMOVE"},
1424 {SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_CLEAR, "SRP_CLIENT_HOST_SERVICES_CLEAR"},
1425 {SPINEL_PROP_SRP_CLIENT_EVENT, "SRP_CLIENT_EVENT"},
1426 {SPINEL_PROP_SRP_CLIENT_SERVICE_KEY_ENABLED, "SRP_CLIENT_SERVICE_KEY_ENABLED"},
1427 {SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE, "SERVER_ALLOW_LOCAL_DATA_CHANGE"},
1428 {SPINEL_PROP_SERVER_SERVICES, "SERVER_SERVICES"},
1429 {SPINEL_PROP_SERVER_LEADER_SERVICES, "SERVER_LEADER_SERVICES"},
1430 {SPINEL_PROP_RCP_API_VERSION, "RCP_API_VERSION"},
1431 {SPINEL_PROP_RCP_MIN_HOST_API_VERSION, "RCP_MIN_HOST_API_VERSION"},
1432 {SPINEL_PROP_RCP_LOG_CRASH_DUMP, "RCP_LOG_CRASH_DUMP"},
1433 {SPINEL_PROP_UART_BITRATE, "UART_BITRATE"},
1434 {SPINEL_PROP_UART_XON_XOFF, "UART_XON_XOFF"},
1435 {SPINEL_PROP_15_4_PIB_PHY_CHANNELS_SUPPORTED, "15_4_PIB_PHY_CHANNELS_SUPPORTED"},
1436 {SPINEL_PROP_15_4_PIB_MAC_PROMISCUOUS_MODE, "15_4_PIB_MAC_PROMISCUOUS_MODE"},
1437 {SPINEL_PROP_15_4_PIB_MAC_SECURITY_ENABLED, "15_4_PIB_MAC_SECURITY_ENABLED"},
1438 {SPINEL_PROP_CNTR_RESET, "CNTR_RESET"},
1439 {SPINEL_PROP_CNTR_TX_PKT_TOTAL, "CNTR_TX_PKT_TOTAL"},
1440 {SPINEL_PROP_CNTR_TX_PKT_ACK_REQ, "CNTR_TX_PKT_ACK_REQ"},
1441 {SPINEL_PROP_CNTR_TX_PKT_ACKED, "CNTR_TX_PKT_ACKED"},
1442 {SPINEL_PROP_CNTR_TX_PKT_NO_ACK_REQ, "CNTR_TX_PKT_NO_ACK_REQ"},
1443 {SPINEL_PROP_CNTR_TX_PKT_DATA, "CNTR_TX_PKT_DATA"},
1444 {SPINEL_PROP_CNTR_TX_PKT_DATA_POLL, "CNTR_TX_PKT_DATA_POLL"},
1445 {SPINEL_PROP_CNTR_TX_PKT_BEACON, "CNTR_TX_PKT_BEACON"},
1446 {SPINEL_PROP_CNTR_TX_PKT_BEACON_REQ, "CNTR_TX_PKT_BEACON_REQ"},
1447 {SPINEL_PROP_CNTR_TX_PKT_OTHER, "CNTR_TX_PKT_OTHER"},
1448 {SPINEL_PROP_CNTR_TX_PKT_RETRY, "CNTR_TX_PKT_RETRY"},
1449 {SPINEL_PROP_CNTR_TX_ERR_CCA, "CNTR_TX_ERR_CCA"},
1450 {SPINEL_PROP_CNTR_TX_PKT_UNICAST, "CNTR_TX_PKT_UNICAST"},
1451 {SPINEL_PROP_CNTR_TX_PKT_BROADCAST, "CNTR_TX_PKT_BROADCAST"},
1452 {SPINEL_PROP_CNTR_TX_ERR_ABORT, "CNTR_TX_ERR_ABORT"},
1453 {SPINEL_PROP_CNTR_RX_PKT_TOTAL, "CNTR_RX_PKT_TOTAL"},
1454 {SPINEL_PROP_CNTR_RX_PKT_DATA, "CNTR_RX_PKT_DATA"},
1455 {SPINEL_PROP_CNTR_RX_PKT_DATA_POLL, "CNTR_RX_PKT_DATA_POLL"},
1456 {SPINEL_PROP_CNTR_RX_PKT_BEACON, "CNTR_RX_PKT_BEACON"},
1457 {SPINEL_PROP_CNTR_RX_PKT_BEACON_REQ, "CNTR_RX_PKT_BEACON_REQ"},
1458 {SPINEL_PROP_CNTR_RX_PKT_OTHER, "CNTR_RX_PKT_OTHER"},
1459 {SPINEL_PROP_CNTR_RX_PKT_FILT_WL, "CNTR_RX_PKT_FILT_WL"},
1460 {SPINEL_PROP_CNTR_RX_PKT_FILT_DA, "CNTR_RX_PKT_FILT_DA"},
1461 {SPINEL_PROP_CNTR_RX_ERR_EMPTY, "CNTR_RX_ERR_EMPTY"},
1462 {SPINEL_PROP_CNTR_RX_ERR_UKWN_NBR, "CNTR_RX_ERR_UKWN_NBR"},
1463 {SPINEL_PROP_CNTR_RX_ERR_NVLD_SADDR, "CNTR_RX_ERR_NVLD_SADDR"},
1464 {SPINEL_PROP_CNTR_RX_ERR_SECURITY, "CNTR_RX_ERR_SECURITY"},
1465 {SPINEL_PROP_CNTR_RX_ERR_BAD_FCS, "CNTR_RX_ERR_BAD_FCS"},
1466 {SPINEL_PROP_CNTR_RX_ERR_OTHER, "CNTR_RX_ERR_OTHER"},
1467 {SPINEL_PROP_CNTR_RX_PKT_DUP, "CNTR_RX_PKT_DUP"},
1468 {SPINEL_PROP_CNTR_RX_PKT_UNICAST, "CNTR_RX_PKT_UNICAST"},
1469 {SPINEL_PROP_CNTR_RX_PKT_BROADCAST, "CNTR_RX_PKT_BROADCAST"},
1470 {SPINEL_PROP_CNTR_TX_IP_SEC_TOTAL, "CNTR_TX_IP_SEC_TOTAL"},
1471 {SPINEL_PROP_CNTR_TX_IP_INSEC_TOTAL, "CNTR_TX_IP_INSEC_TOTAL"},
1472 {SPINEL_PROP_CNTR_TX_IP_DROPPED, "CNTR_TX_IP_DROPPED"},
1473 {SPINEL_PROP_CNTR_RX_IP_SEC_TOTAL, "CNTR_RX_IP_SEC_TOTAL"},
1474 {SPINEL_PROP_CNTR_RX_IP_INSEC_TOTAL, "CNTR_RX_IP_INSEC_TOTAL"},
1475 {SPINEL_PROP_CNTR_RX_IP_DROPPED, "CNTR_RX_IP_DROPPED"},
1476 {SPINEL_PROP_CNTR_TX_SPINEL_TOTAL, "CNTR_TX_SPINEL_TOTAL"},
1477 {SPINEL_PROP_CNTR_RX_SPINEL_TOTAL, "CNTR_RX_SPINEL_TOTAL"},
1478 {SPINEL_PROP_CNTR_RX_SPINEL_ERR, "CNTR_RX_SPINEL_ERR"},
1479 {SPINEL_PROP_CNTR_RX_SPINEL_OUT_OF_ORDER_TID, "CNTR_RX_SPINEL_OUT_OF_ORDER_TID"},
1480 {SPINEL_PROP_CNTR_IP_TX_SUCCESS, "CNTR_IP_TX_SUCCESS"},
1481 {SPINEL_PROP_CNTR_IP_RX_SUCCESS, "CNTR_IP_RX_SUCCESS"},
1482 {SPINEL_PROP_CNTR_IP_TX_FAILURE, "CNTR_IP_TX_FAILURE"},
1483 {SPINEL_PROP_CNTR_IP_RX_FAILURE, "CNTR_IP_RX_FAILURE"},
1484 {SPINEL_PROP_MSG_BUFFER_COUNTERS, "MSG_BUFFER_COUNTERS"},
1485 {SPINEL_PROP_CNTR_ALL_MAC_COUNTERS, "CNTR_ALL_MAC_COUNTERS"},
1486 {SPINEL_PROP_CNTR_MLE_COUNTERS, "CNTR_MLE_COUNTERS"},
1487 {SPINEL_PROP_CNTR_ALL_IP_COUNTERS, "CNTR_ALL_IP_COUNTERS"},
1488 {SPINEL_PROP_CNTR_MAC_RETRY_HISTOGRAM, "CNTR_MAC_RETRY_HISTOGRAM"},
1489 {SPINEL_PROP_NEST_STREAM_MFG, "NEST_STREAM_MFG"},
1490 {SPINEL_PROP_DEBUG_TEST_ASSERT, "DEBUG_TEST_ASSERT"},
1491 {SPINEL_PROP_DEBUG_NCP_LOG_LEVEL, "DEBUG_NCP_LOG_LEVEL"},
1492 {SPINEL_PROP_DEBUG_TEST_WATCHDOG, "DEBUG_TEST_WATCHDOG"},
1493 {SPINEL_PROP_RCP_MAC_FRAME_COUNTER, "RCP_MAC_FRAME_COUNTER"},
1494 {SPINEL_PROP_RCP_MAC_KEY, "RCP_MAC_KEY"},
1495 {SPINEL_PROP_DEBUG_LOG_TIMESTAMP_BASE, "DEBUG_LOG_TIMESTAMP_BASE"},
1496 {SPINEL_PROP_DEBUG_TREL_TEST_MODE_ENABLE, "DEBUG_TREL_TEST_MODE_ENABLE"},
1497 {0, NULL},
1498 };
1499
1500 return spinel_to_cstr(spinel_prop_cstr, prop_key);
1501 }
1502
spinel_net_role_to_cstr(uint8_t net_role)1503 const char *spinel_net_role_to_cstr(uint8_t net_role)
1504 {
1505 static const struct spinel_cstr spinel_net_cstr[] = {
1506 {SPINEL_NET_ROLE_DETACHED, "NET_ROLE_DETACHED"}, {SPINEL_NET_ROLE_CHILD, "NET_ROLE_CHILD"},
1507 {SPINEL_NET_ROLE_ROUTER, "NET_ROLE_ROUTER"}, {SPINEL_NET_ROLE_LEADER, "NET_ROLE_LEADER"},
1508 {SPINEL_NET_ROLE_DISABLED, "NET_ROLE_DISABLED"}, {0, NULL},
1509 };
1510
1511 return spinel_to_cstr(spinel_net_cstr, net_role);
1512 }
1513
spinel_mcu_power_state_to_cstr(uint8_t mcu_power_state)1514 const char *spinel_mcu_power_state_to_cstr(uint8_t mcu_power_state)
1515 {
1516 static const struct spinel_cstr spinel_mcu_power_state_cstr[] = {
1517 {SPINEL_MCU_POWER_STATE_ON, "MCU_POWER_STATE_ON"},
1518 {SPINEL_MCU_POWER_STATE_LOW_POWER, "MCU_POWER_STATE_LOW_POWER"},
1519 {SPINEL_MCU_POWER_STATE_OFF, "MCU_POWER_STATE_OFF"},
1520 {0, NULL},
1521 };
1522
1523 return spinel_to_cstr(spinel_mcu_power_state_cstr, mcu_power_state);
1524 }
1525
spinel_status_to_cstr(spinel_status_t status)1526 const char *spinel_status_to_cstr(spinel_status_t status)
1527 {
1528 static const struct spinel_cstr spinel_status_cstr[] = {
1529 {SPINEL_STATUS_OK, "OK"},
1530 {SPINEL_STATUS_FAILURE, "FAILURE"},
1531 {SPINEL_STATUS_UNIMPLEMENTED, "UNIMPLEMENTED"},
1532 {SPINEL_STATUS_INVALID_ARGUMENT, "INVALID_ARGUMENT"},
1533 {SPINEL_STATUS_INVALID_STATE, "INVALID_STATE"},
1534 {SPINEL_STATUS_INVALID_COMMAND, "INVALID_COMMAND"},
1535 {SPINEL_STATUS_INVALID_INTERFACE, "INVALID_INTERFACE"},
1536 {SPINEL_STATUS_INTERNAL_ERROR, "INTERNAL_ERROR"},
1537 {SPINEL_STATUS_SECURITY_ERROR, "SECURITY_ERROR"},
1538 {SPINEL_STATUS_PARSE_ERROR, "PARSE_ERROR"},
1539 {SPINEL_STATUS_IN_PROGRESS, "IN_PROGRESS"},
1540 {SPINEL_STATUS_NOMEM, "NOMEM"},
1541 {SPINEL_STATUS_BUSY, "BUSY"},
1542 {SPINEL_STATUS_PROP_NOT_FOUND, "PROP_NOT_FOUND"},
1543 {SPINEL_STATUS_DROPPED, "DROPPED"},
1544 {SPINEL_STATUS_EMPTY, "EMPTY"},
1545 {SPINEL_STATUS_CMD_TOO_BIG, "CMD_TOO_BIG"},
1546 {SPINEL_STATUS_NO_ACK, "NO_ACK"},
1547 {SPINEL_STATUS_CCA_FAILURE, "CCA_FAILURE"},
1548 {SPINEL_STATUS_ALREADY, "ALREADY"},
1549 {SPINEL_STATUS_ITEM_NOT_FOUND, "ITEM_NOT_FOUND"},
1550 {SPINEL_STATUS_INVALID_COMMAND_FOR_PROP, "INVALID_COMMAND_FOR_PROP"},
1551 {SPINEL_STATUS_RESPONSE_TIMEOUT, "RESPONSE_TIMEOUT"},
1552 {SPINEL_STATUS_SWITCHOVER_DONE, "SWITCHOVER_DONE"},
1553 {SPINEL_STATUS_SWITCHOVER_FAILED, "SWITCHOVER_FAILED"},
1554 {SPINEL_STATUS_JOIN_FAILURE, "JOIN_FAILURE"},
1555 {SPINEL_STATUS_JOIN_SECURITY, "JOIN_SECURITY"},
1556 {SPINEL_STATUS_JOIN_NO_PEERS, "JOIN_NO_PEERS"},
1557 {SPINEL_STATUS_JOIN_INCOMPATIBLE, "JOIN_INCOMPATIBLE"},
1558 {SPINEL_STATUS_JOIN_RSP_TIMEOUT, "JOIN_RSP_TIMEOUT"},
1559 {SPINEL_STATUS_JOIN_SUCCESS, "JOIN_SUCCESS"},
1560 {SPINEL_STATUS_RESET_POWER_ON, "RESET_POWER_ON"},
1561 {SPINEL_STATUS_RESET_EXTERNAL, "RESET_EXTERNAL"},
1562 {SPINEL_STATUS_RESET_SOFTWARE, "RESET_SOFTWARE"},
1563 {SPINEL_STATUS_RESET_FAULT, "RESET_FAULT"},
1564 {SPINEL_STATUS_RESET_CRASH, "RESET_CRASH"},
1565 {SPINEL_STATUS_RESET_ASSERT, "RESET_ASSERT"},
1566 {SPINEL_STATUS_RESET_OTHER, "RESET_OTHER"},
1567 {SPINEL_STATUS_RESET_UNKNOWN, "RESET_UNKNOWN"},
1568 {SPINEL_STATUS_RESET_WATCHDOG, "RESET_WATCHDOG"},
1569 {0, NULL},
1570 };
1571
1572 return spinel_to_cstr(spinel_status_cstr, status);
1573 }
1574
spinel_capability_to_cstr(spinel_capability_t capability)1575 const char *spinel_capability_to_cstr(spinel_capability_t capability)
1576 {
1577 static const struct spinel_cstr spinel_cap_cstr[] = {
1578 {SPINEL_CAP_LOCK, "LOCK"},
1579 {SPINEL_CAP_NET_SAVE, "NET_SAVE"},
1580 {SPINEL_CAP_HBO, "HBO"},
1581 {SPINEL_CAP_POWER_SAVE, "POWER_SAVE"},
1582 {SPINEL_CAP_COUNTERS, "COUNTERS"},
1583 {SPINEL_CAP_JAM_DETECT, "JAM_DETECT"},
1584 {SPINEL_CAP_PEEK_POKE, "PEEK_POKE"},
1585 {SPINEL_CAP_WRITABLE_RAW_STREAM, "WRITABLE_RAW_STREAM"},
1586 {SPINEL_CAP_GPIO, "GPIO"},
1587 {SPINEL_CAP_TRNG, "TRNG"},
1588 {SPINEL_CAP_CMD_MULTI, "CMD_MULTI"},
1589 {SPINEL_CAP_UNSOL_UPDATE_FILTER, "UNSOL_UPDATE_FILTER"},
1590 {SPINEL_CAP_MCU_POWER_STATE, "MCU_POWER_STATE"},
1591 {SPINEL_CAP_PCAP, "PCAP"},
1592 {SPINEL_CAP_802_15_4_2003, "802_15_4_2003"},
1593 {SPINEL_CAP_802_15_4_2006, "802_15_4_2006"},
1594 {SPINEL_CAP_802_15_4_2011, "802_15_4_2011"},
1595 {SPINEL_CAP_802_15_4_PIB, "802_15_4_PIB"},
1596 {SPINEL_CAP_802_15_4_2450MHZ_OQPSK, "802_15_4_2450MHZ_OQPSK"},
1597 {SPINEL_CAP_802_15_4_915MHZ_OQPSK, "802_15_4_915MHZ_OQPSK"},
1598 {SPINEL_CAP_802_15_4_868MHZ_OQPSK, "802_15_4_868MHZ_OQPSK"},
1599 {SPINEL_CAP_802_15_4_915MHZ_BPSK, "802_15_4_915MHZ_BPSK"},
1600 {SPINEL_CAP_802_15_4_868MHZ_BPSK, "802_15_4_868MHZ_BPSK"},
1601 {SPINEL_CAP_802_15_4_915MHZ_ASK, "802_15_4_915MHZ_ASK"},
1602 {SPINEL_CAP_802_15_4_868MHZ_ASK, "802_15_4_868MHZ_ASK"},
1603 {SPINEL_CAP_CONFIG_FTD, "CONFIG_FTD"},
1604 {SPINEL_CAP_CONFIG_MTD, "CONFIG_MTD"},
1605 {SPINEL_CAP_CONFIG_RADIO, "CONFIG_RADIO"},
1606 {SPINEL_CAP_ROLE_ROUTER, "ROLE_ROUTER"},
1607 {SPINEL_CAP_ROLE_SLEEPY, "ROLE_SLEEPY"},
1608 {SPINEL_CAP_NET_THREAD_1_0, "NET_THREAD_1_0"},
1609 {SPINEL_CAP_NET_THREAD_1_1, "NET_THREAD_1_1"},
1610 {SPINEL_CAP_NET_THREAD_1_2, "NET_THREAD_1_2"},
1611 {SPINEL_CAP_RCP_API_VERSION, "RCP_API_VERSION"},
1612 {SPINEL_CAP_RCP_MIN_HOST_API_VERSION, "RCP_MIN_HOST_API_VERSION"},
1613 {SPINEL_CAP_RCP_RESET_TO_BOOTLOADER, "RCP_RESET_TO_BOOTLOADER"},
1614 {SPINEL_CAP_RCP_LOG_CRASH_DUMP, "RCP_LOG_CRASH_DUMP"},
1615 {SPINEL_CAP_MAC_ALLOWLIST, "MAC_ALLOWLIST"},
1616 {SPINEL_CAP_MAC_RAW, "MAC_RAW"},
1617 {SPINEL_CAP_OOB_STEERING_DATA, "OOB_STEERING_DATA"},
1618 {SPINEL_CAP_CHANNEL_MONITOR, "CHANNEL_MONITOR"},
1619 {SPINEL_CAP_CHANNEL_MANAGER, "CHANNEL_MANAGER"},
1620 {SPINEL_CAP_OPENTHREAD_LOG_METADATA, "OPENTHREAD_LOG_METADATA"},
1621 {SPINEL_CAP_TIME_SYNC, "TIME_SYNC"},
1622 {SPINEL_CAP_CHILD_SUPERVISION, "CHILD_SUPERVISION"},
1623 {SPINEL_CAP_POSIX, "POSIX"},
1624 {SPINEL_CAP_SLAAC, "SLAAC"},
1625 {SPINEL_CAP_RADIO_COEX, "RADIO_COEX"},
1626 {SPINEL_CAP_MAC_RETRY_HISTOGRAM, "MAC_RETRY_HISTOGRAM"},
1627 {SPINEL_CAP_MULTI_RADIO, "MULTI_RADIO"},
1628 {SPINEL_CAP_SRP_CLIENT, "SRP_CLIENT"},
1629 {SPINEL_CAP_DUA, "DUA"},
1630 {SPINEL_CAP_REFERENCE_DEVICE, "REFERENCE_DEVICE"},
1631 {SPINEL_CAP_ERROR_RATE_TRACKING, "ERROR_RATE_TRACKING"},
1632 {SPINEL_CAP_THREAD_COMMISSIONER, "THREAD_COMMISSIONER"},
1633 {SPINEL_CAP_THREAD_TMF_PROXY, "THREAD_TMF_PROXY"},
1634 {SPINEL_CAP_THREAD_UDP_FORWARD, "THREAD_UDP_FORWARD"},
1635 {SPINEL_CAP_THREAD_JOINER, "THREAD_JOINER"},
1636 {SPINEL_CAP_THREAD_BORDER_ROUTER, "THREAD_BORDER_ROUTER"},
1637 {SPINEL_CAP_THREAD_SERVICE, "THREAD_SERVICE"},
1638 {SPINEL_CAP_THREAD_CSL_RECEIVER, "THREAD_CSL_RECEIVER"},
1639 {SPINEL_CAP_THREAD_BACKBONE_ROUTER, "THREAD_BACKBONE_ROUTER"},
1640 {SPINEL_CAP_NEST_TRANSMIT_HOOK, "NEST_TRANSMIT_HOOK"},
1641 {0, NULL},
1642 };
1643
1644 return spinel_to_cstr(spinel_cap_cstr, capability);
1645 }
1646
1647 // LCOV_EXCL_STOP
1648
1649 /* -------------------------------------------------------------------------- */
1650
1651 #if SPINEL_SELF_TEST
1652
main(void)1653 int main(void)
1654 {
1655 int ret = -1;
1656 const spinel_eui64_t static_eui64 = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}};
1657 const char static_string[] = "static_string";
1658 uint8_t buffer[1024];
1659 ssize_t len;
1660
1661 len =
1662 spinel_datatype_pack(buffer, sizeof(buffer), "CiiLUE", 0x88, 9, 0xA3, 0xDEADBEEF, static_string, &static_eui64);
1663
1664 if (len != 30)
1665 {
1666 printf("error:%d: len != 30; (%d)\n", __LINE__, (int)len);
1667 goto bail;
1668 }
1669
1670 {
1671 const char *str = NULL;
1672
1673 // Length ends right before the string.
1674 len = spinel_datatype_unpack(buffer, 8, "CiiLU", NULL, NULL, NULL, NULL, &str);
1675
1676 if (len != -1)
1677 {
1678 printf("error:%d: len != -1; (%d)\n", __LINE__, (int)len);
1679 goto bail;
1680 }
1681
1682 if (str != NULL)
1683 {
1684 printf("error:%d: str != NULL\n", __LINE__);
1685 goto bail;
1686 }
1687 }
1688
1689 len = 30;
1690
1691 {
1692 uint8_t c = 0;
1693 unsigned int i1 = 0;
1694 unsigned int i2 = 0;
1695 uint32_t l = 0;
1696 const char *str = NULL;
1697 const spinel_eui64_t *eui64 = NULL;
1698
1699 len = spinel_datatype_unpack(buffer, (spinel_size_t)len, "CiiLUE", &c, &i1, &i2, &l, &str, &eui64);
1700
1701 if (len != 30)
1702 {
1703 printf("error:%d: len != 30; (%d)\n", __LINE__, (int)len);
1704 goto bail;
1705 }
1706
1707 if (c != 0x88)
1708 {
1709 printf("error: x != 0x88; (%d)\n", c);
1710 goto bail;
1711 }
1712
1713 if (i1 != 9)
1714 {
1715 printf("error: i1 != 9; (%d)\n", i1);
1716 goto bail;
1717 }
1718
1719 if (i2 != 0xA3)
1720 {
1721 printf("error: i2 != 0xA3; (0x%02X)\n", i2);
1722 goto bail;
1723 }
1724
1725 if (l != 0xDEADBEEF)
1726 {
1727 printf("error: l != 0xDEADBEEF; (0x%08X)\n", (unsigned int)l);
1728 goto bail;
1729 }
1730
1731 if (strcmp(str, static_string) != 0)
1732 {
1733 printf("error:%d: strcmp(str,static_string) != 0\n", __LINE__);
1734 goto bail;
1735 }
1736
1737 if (memcmp(eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0)
1738 {
1739 printf("error:%d: memcmp(eui64, &eui64, sizeof(spinel_eui64_t)) != 0\n", __LINE__);
1740 goto bail;
1741 }
1742 }
1743
1744 {
1745 uint8_t c = 0;
1746 unsigned int i1 = 0;
1747 unsigned int i2 = 0;
1748 uint32_t l = 0;
1749 char str[sizeof(static_string)];
1750 spinel_eui64_t eui64 = {{0}};
1751
1752 len = spinel_datatype_unpack_in_place(buffer, (spinel_size_t)len, "CiiLUE", &c, &i1, &i2, &l, &str, sizeof(str),
1753 &eui64);
1754
1755 if (len != 30)
1756 {
1757 printf("error:%d: len != 30; (%d)\n", __LINE__, (int)len);
1758 goto bail;
1759 }
1760
1761 if (c != 0x88)
1762 {
1763 printf("error: x != 0x88; (%d)\n", c);
1764 goto bail;
1765 }
1766
1767 if (i1 != 9)
1768 {
1769 printf("error: i1 != 9; (%d)\n", i1);
1770 goto bail;
1771 }
1772
1773 if (i2 != 0xA3)
1774 {
1775 printf("error: i2 != 0xA3; (0x%02X)\n", i2);
1776 goto bail;
1777 }
1778
1779 if (l != 0xDEADBEEF)
1780 {
1781 printf("error: l != 0xDEADBEEF; (0x%08X)\n", (unsigned int)l);
1782 goto bail;
1783 }
1784
1785 if (strcmp(str, static_string) != 0)
1786 {
1787 printf("error:%d: strcmp(str,static_string) != 0\n", __LINE__);
1788 goto bail;
1789 }
1790
1791 if (memcmp(&eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0)
1792 {
1793 printf("error:%d: memcmp(&eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0\n", __LINE__);
1794 goto bail;
1795 }
1796 }
1797
1798 // -----------------------------------
1799
1800 memset(buffer, 0xAA, sizeof(buffer));
1801
1802 len = spinel_datatype_pack(buffer, sizeof(buffer), "Cit(iL)UE", 0x88, 9, 0xA3, 0xDEADBEEF, static_string,
1803 &static_eui64);
1804
1805 if (len != 32)
1806 {
1807 printf("error:%d: len != 32; (%d)\n", __LINE__, (int)len);
1808 goto bail;
1809 }
1810
1811 {
1812 uint8_t c = 0;
1813 unsigned int i1 = 0;
1814 unsigned int i2 = 0;
1815 uint32_t l = 0;
1816 const char *str = NULL;
1817 spinel_eui64_t *eui64 = NULL;
1818
1819 len = spinel_datatype_unpack(buffer, (spinel_size_t)len, "Cit(iL)UE", &c, &i1, &i2, &l, &str, &eui64);
1820
1821 if (len != 32)
1822 {
1823 printf("error:%d: len != 24; (%d)\n", __LINE__, (int)len);
1824 goto bail;
1825 }
1826
1827 if (c != 0x88)
1828 {
1829 printf("error: x != 0x88; (%d)\n", c);
1830 goto bail;
1831 }
1832
1833 if (i1 != 9)
1834 {
1835 printf("error: i1 != 9; (%d)\n", i1);
1836 goto bail;
1837 }
1838
1839 if (i2 != 0xA3)
1840 {
1841 printf("error: i2 != 0xA3; (0x%02X)\n", i2);
1842 goto bail;
1843 }
1844
1845 if (l != 0xDEADBEEF)
1846 {
1847 printf("error: l != 0xDEADBEEF; (0x%08X)\n", (unsigned int)l);
1848 goto bail;
1849 }
1850
1851 if (strcmp(str, static_string) != 0)
1852 {
1853 printf("error:%d: strcmp(str,static_string) != 0\n", __LINE__);
1854 goto bail;
1855 }
1856
1857 if (memcmp(eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0)
1858 {
1859 printf("error:%d: memcmp(eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0\n", __LINE__);
1860 goto bail;
1861 }
1862 }
1863
1864 {
1865 uint8_t c = 0;
1866 unsigned int i1 = 0;
1867 unsigned int i2 = 0;
1868 uint32_t l = 0;
1869 char str[sizeof(static_string)];
1870 spinel_eui64_t eui64 = {{0}};
1871
1872 len = spinel_datatype_unpack_in_place(buffer, (spinel_size_t)len, "Cit(iL)UE", &c, &i1, &i2, &l, &str,
1873 sizeof(str), &eui64);
1874
1875 if (len != 32)
1876 {
1877 printf("error:%d: len != 24; (%d)\n", __LINE__, (int)len);
1878 goto bail;
1879 }
1880
1881 if (c != 0x88)
1882 {
1883 printf("error: x != 0x88; (%d)\n", c);
1884 goto bail;
1885 }
1886
1887 if (i1 != 9)
1888 {
1889 printf("error: i1 != 9; (%d)\n", i1);
1890 goto bail;
1891 }
1892
1893 if (i2 != 0xA3)
1894 {
1895 printf("error: i2 != 0xA3; (0x%02X)\n", i2);
1896 goto bail;
1897 }
1898
1899 if (l != 0xDEADBEEF)
1900 {
1901 printf("error: l != 0xDEADBEEF; (0x%08X)\n", (unsigned int)l);
1902 goto bail;
1903 }
1904
1905 if (strcmp(str, static_string) != 0)
1906 {
1907 printf("error:%d: strcmp(str,static_string) != 0\n", __LINE__);
1908 goto bail;
1909 }
1910
1911 if (memcmp(&eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0)
1912 {
1913 printf("error:%d: memcmp(&eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0\n", __LINE__);
1914 goto bail;
1915 }
1916 }
1917
1918 {
1919 // Test UTF8 validation - Good/Valid strings
1920
1921 // Single symbols
1922 const uint8_t single1[] = {0}; // 0000
1923 const uint8_t single2[] = {0x7F, 0x00}; // 007F
1924 const uint8_t single3[] = {0xC2, 0x80, 0x00}; // 080
1925 const uint8_t single4[] = {0xDF, 0xBF, 0x00}; // 07FF
1926 const uint8_t single5[] = {0xE0, 0xA0, 0x80, 0x00}; // 0800
1927 const uint8_t single6[] = {0xEF, 0xBF, 0xBF, 0x00}; // FFFF
1928 const uint8_t single7[] = {0xF0, 0x90, 0x80, 0x80, 0x00}; // 010000
1929 const uint8_t single8[] = {0xF4, 0x8F, 0xBF, 0xBF, 0x00}; // 10FFFF
1930
1931 // Strings
1932 const uint8_t str1[] = "spinel";
1933 const uint8_t str2[] = "OpenThread";
1934 const uint8_t str3[] = {0x41, 0x7F, 0xEF, 0xBF, 0xBF, 0xC2, 0x80, 0x21, 0x33, 0x00};
1935 const uint8_t str4[] = {0xCE, 0xBA, 0xE1, 0xBD, 0xB9, 0xCF, 0x83, 0xCE, 0xBC, 0xCE, 0xB5, 0x00}; // κόσμε
1936 const uint8_t str5[] = {0x3D, 0xF4, 0x8F, 0xBF, 0xBF, 0x01, 0xE0, 0xA0, 0x83, 0x22, 0xEF, 0xBF, 0xBF, 0x00};
1937 const uint8_t str6[] = {0xE5, 0xA2, 0x82, 0xE0, 0xA0, 0x80, 0xC2, 0x83, 0xC2, 0x80, 0xF4,
1938 0x8F, 0xBF, 0xBF, 0xF4, 0x8F, 0xBF, 0xBF, 0xDF, 0xBF, 0x21, 0x00};
1939
1940 const uint8_t *good_strings[] = {single1, single2, single3, single4, single5, single6, single7, single8,
1941 str1, str2, str3, str4, str5, str6, NULL};
1942 const uint8_t **str_ptr;
1943
1944 for (str_ptr = &good_strings[0]; *str_ptr != NULL; str_ptr++)
1945 {
1946 if (!spinel_validate_utf8(*str_ptr))
1947 {
1948 printf("error: spinel_validate_utf8() did not correctly detect a valid UTF8 sequence!\n");
1949 goto bail;
1950 }
1951 }
1952 }
1953
1954 {
1955 // Test UTF8 validation - Bad/Invalid strings
1956
1957 // Single symbols (invalid)
1958 const uint8_t single1[] = {0xF8, 0x00};
1959 const uint8_t single2[] = {0xF9, 0x00};
1960 const uint8_t single3[] = {0xFA, 0x00};
1961 const uint8_t single4[] = {0xFF, 0x00};
1962
1963 // Bad continuations
1964 const uint8_t bad1[] = {0xDF, 0x0F, 0x00};
1965 const uint8_t bad2[] = {0xE0, 0xA0, 0x10, 0x00};
1966 const uint8_t bad3[] = {0xF0, 0x90, 0x80, 0x60, 0x00};
1967 const uint8_t bad4[] = {0xF4, 0x8F, 0xBF, 0x0F, 0x00};
1968 const uint8_t bad5[] = {0x21, 0xA0, 0x00};
1969 const uint8_t bad6[] = {0xCE, 0xBA, 0xE1, 0xBD, 0xB9, 0xCF, 0x83, 0xCE, 0xBC, 0xCE, 0x00};
1970
1971 const uint8_t *bad_strings[] = {single1, single2, single3, single4, bad1, bad2, bad3, bad4, bad5, bad6, NULL};
1972 const uint8_t **str_ptr;
1973
1974 for (str_ptr = &bad_strings[0]; *str_ptr != NULL; str_ptr++)
1975 {
1976 if (spinel_validate_utf8(*str_ptr))
1977 {
1978 printf("error: spinel_validate_utf8() did not correctly detect an invalid UTF8 sequence\n");
1979 goto bail;
1980 }
1981 }
1982 }
1983
1984 printf("OK\n");
1985 ret = 0;
1986 return ret;
1987
1988 bail:
1989 printf("FAILURE\n");
1990 return ret;
1991 }
1992
1993 #endif // #if SPINEL_SELF_TEST
1994