Coverage Report

Created: 2026-01-16 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wpantund/src/ncp-spinel/SpinelNCPInstance.cpp
Line
Count
Source
1
/*
2
 *
3
 * Copyright (c) 2016 Nest Labs, Inc.
4
 * All rights reserved.
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 *
18
 */
19
20
#if HAVE_CONFIG_H
21
#include <config.h>
22
#endif
23
24
#include <algorithm>
25
#include <inttypes.h>
26
#include "SpinelNCPInstance.h"
27
#include "time-utils.h"
28
#include "assert-macros.h"
29
#include <syslog.h>
30
#include <errno.h>
31
#include "socket-utils.h"
32
#include <stdexcept>
33
#include <sys/file.h>
34
#include "SuperSocket.h"
35
#include "SpinelNCPTask.h"
36
#include "SpinelNCPTaskWake.h"
37
#include "SpinelNCPTaskSendCommand.h"
38
#include "SpinelNCPTaskJoin.h"
39
#include "SpinelNCPTaskGetNetworkTopology.h"
40
#include "SpinelNCPTaskGetMsgBufferCounters.h"
41
#include "SpinelNCPThreadDataset.h"
42
#include "any-to.h"
43
#include "spinel-extra.h"
44
#include "IPv6Helpers.h"
45
46
0
#define kWPANTUND_Allowlist_RssiOverrideDisabled    127
47
0
#define kWPANTUND_SpinelPropValueDumpLen            8
48
49
using namespace nl;
50
using namespace wpantund;
51
52
WPANTUND_DEFINE_NCPINSTANCE_PLUGIN(spinel, SpinelNCPInstance);
53
54
void
55
SpinelNCPInstance::handle_ncp_debug_stream(const uint8_t* data_ptr, int data_len)
56
454
{
57
454
  static char linebuffer[NCP_DEBUG_LINE_LENGTH_MAX + 1];
58
454
  static int linepos = 0;
59
8.11k
  while (data_len--) {
60
7.65k
    char nextchar = *data_ptr++;
61
62
7.65k
    if ((nextchar == '\t') || (nextchar >= 32)) {
63
4.49k
      linebuffer[linepos++] = nextchar;
64
4.49k
    }
65
66
7.65k
    if ( (linepos != 0)
67
7.10k
      && ( (nextchar == '\n')
68
6.81k
      || (nextchar == '\r')
69
6.53k
      || (linepos >= (sizeof(linebuffer) - 1))
70
7.10k
      )
71
7.65k
    )
72
577
    {
73
      // flush.
74
577
      linebuffer[linepos] = 0;
75
577
      syslog(LOG_WARNING, "NCP => %s\n", linebuffer);
76
577
      linepos = 0;
77
577
    }
78
7.65k
  }
79
454
}
80
81
static const char *
82
ot_log_level_to_string(uint8_t log_level)
83
1.51k
{
84
1.51k
  const char *retval = "----";
85
86
1.51k
  switch (log_level)
87
1.51k
  {
88
101
  case SPINEL_NCP_LOG_LEVEL_EMERG:
89
101
    retval = "EMRG";
90
101
    break;
91
92
32
  case SPINEL_NCP_LOG_LEVEL_ALERT:
93
32
    retval = "ALRT";
94
32
    break;
95
96
9
  case SPINEL_NCP_LOG_LEVEL_CRIT:
97
9
    retval = "CRIT";
98
9
    break;
99
100
639
  case SPINEL_NCP_LOG_LEVEL_ERR:
101
639
    retval = "ERR ";
102
639
    break;
103
104
33
  case SPINEL_NCP_LOG_LEVEL_WARN:
105
33
    retval = "WARN";
106
33
    break;
107
108
17
  case SPINEL_NCP_LOG_LEVEL_NOTICE:
109
17
    retval = "NOTE";
110
17
    break;
111
112
50
  case SPINEL_NCP_LOG_LEVEL_INFO:
113
50
    retval = "INFO";
114
50
    break;
115
116
100
  case SPINEL_NCP_LOG_LEVEL_DEBUG:
117
100
    retval = "DEBG";
118
100
    break;
119
1.51k
  }
120
121
1.51k
  return retval;
122
1.51k
}
123
124
static const char *
125
ot_log_region_to_string(unsigned int log_region)
126
1.51k
{
127
1.51k
  const char *retval = "---------";
128
129
1.51k
  switch (log_region)
130
1.51k
  {
131
8
  case SPINEL_NCP_LOG_REGION_OT_API:
132
8
    retval = "-API-----";
133
8
    break;
134
135
66
  case SPINEL_NCP_LOG_REGION_OT_MLE:
136
66
    retval = "-MLE-----";
137
66
    break;
138
139
27
  case SPINEL_NCP_LOG_REGION_OT_COAP:
140
27
    retval = "-COAP----";
141
27
    break;
142
143
23
  case SPINEL_NCP_LOG_REGION_OT_ARP:
144
23
    retval = "-ARP-----";
145
23
    break;
146
147
0
  case SPINEL_NCP_LOG_REGION_OT_NET_DATA:
148
0
    retval = "-N-DATA--";
149
0
    break;
150
151
12
  case SPINEL_NCP_LOG_REGION_OT_ICMP:
152
12
    retval = "-ICMP----";
153
12
    break;
154
155
206
  case SPINEL_NCP_LOG_REGION_OT_IP6:
156
206
    retval = "-IP6-----";
157
206
    break;
158
159
19
  case SPINEL_NCP_LOG_REGION_OT_MAC:
160
19
    retval = "-MAC-----";
161
19
    break;
162
163
0
  case SPINEL_NCP_LOG_REGION_OT_MEM:
164
0
    retval = "-MEM-----";
165
0
    break;
166
167
19
  case SPINEL_NCP_LOG_REGION_OT_NCP:
168
19
    retval = "-NCP-----";
169
19
    break;
170
171
5
  case SPINEL_NCP_LOG_REGION_OT_MESH_COP:
172
5
    retval = "-MESH-CP-";
173
5
    break;
174
175
2
  case SPINEL_NCP_LOG_REGION_OT_NET_DIAG:
176
2
    retval = "-DIAG----";
177
2
    break;
178
179
3
  case SPINEL_NCP_LOG_REGION_OT_PLATFORM:
180
3
    retval = "-PLAT----";
181
3
    break;
182
183
29
  case SPINEL_NCP_LOG_REGION_OT_CORE:
184
29
    retval = "-CORE----";
185
29
    break;
186
187
689
  case SPINEL_NCP_LOG_REGION_OT_UTIL:
188
689
    retval = "-UTIL----";
189
689
    break;
190
1.51k
  }
191
192
1.51k
  return retval;
193
1.51k
}
194
195
void
196
SpinelNCPInstance::handle_ncp_log_stream(const uint8_t *data_in, int data_len)
197
2.90k
{
198
2.90k
  spinel_ssize_t len;
199
2.90k
  char prefix_string[NCP_DEBUG_LINE_LENGTH_MAX + 1];
200
2.90k
  const char *log_string;
201
202
2.90k
  len = spinel_datatype_unpack(
203
2.90k
    data_in,
204
2.90k
    data_len,
205
2.90k
    SPINEL_DATATYPE_UTF8_S,
206
2.90k
    &log_string
207
2.90k
  );
208
2.90k
  require(len >= 0, bail);
209
210
2.58k
  data_in += len;
211
2.58k
  data_len -= len;
212
213
2.58k
  prefix_string[0] = 0;
214
215
2.58k
  if ((data_len > 0) && mCapabilities.count(SPINEL_CAP_OPENTHREAD_LOG_METADATA)) {
216
1.54k
    uint8_t log_level;
217
1.54k
    unsigned int log_region;
218
1.54k
    uint64_t log_timestamp;
219
220
1.54k
    len = spinel_datatype_unpack(
221
1.54k
      data_in,
222
1.54k
      data_len,
223
1.54k
      (
224
1.54k
        SPINEL_DATATYPE_UINT8_S
225
1.54k
        SPINEL_DATATYPE_UINT_PACKED_S
226
1.54k
      ),
227
1.54k
      &log_level,
228
1.54k
      &log_region
229
1.54k
    );
230
1.54k
    require(len >= 0, bail);
231
232
1.51k
    data_in += len;
233
1.51k
    data_len -= len;
234
235
1.51k
    if (data_len >= sizeof(log_timestamp)) {
236
285
      len = spinel_datatype_unpack(
237
285
        data_in,
238
285
        data_len,
239
285
        SPINEL_DATATYPE_UINT64_S,
240
285
        &log_timestamp
241
285
      );
242
285
      require(len >= 0, bail);
243
244
285
      snprintf(
245
285
        prefix_string,
246
285
        sizeof(prefix_string),
247
285
        "[%013llu][%s]%s: ",
248
285
        static_cast<unsigned long long>(log_timestamp),
249
285
        ot_log_level_to_string(log_level),
250
285
        ot_log_region_to_string(log_region)
251
285
      );
252
1.23k
    } else {
253
1.23k
      snprintf(
254
1.23k
        prefix_string,
255
1.23k
        sizeof(prefix_string),
256
1.23k
        "[%s]%s: ",
257
1.23k
        ot_log_level_to_string(log_level),
258
1.23k
        ot_log_region_to_string(log_region)
259
1.23k
      );
260
1.23k
    }
261
1.51k
  }
262
263
2.55k
  syslog(LOG_WARNING, "NCP => %s%s\n", prefix_string, log_string);
264
265
2.90k
bail:
266
2.90k
  return;
267
2.55k
}
268
269
void
270
SpinelNCPInstance::start_new_task(const boost::shared_ptr<SpinelNCPTask> &task)
271
30.5k
{
272
30.5k
  if (ncp_state_is_detached_from_ncp(get_ncp_state())) {
273
0
    task->finish(kWPANTUNDStatus_InvalidWhenDisabled);
274
30.5k
  } else if (PT_SCHEDULE(task->process_event(EVENT_STARTING_TASK))) {
275
276
30.5k
    if (ncp_state_is_sleeping(get_ncp_state())
277
14.5k
      && (dynamic_cast<const SpinelNCPTaskWake*>(task.get()) == NULL)
278
30.5k
    ) {
279
7.32k
      if (can_set_ncp_power()
280
7.32k
        || !mCapabilities.count(SPINEL_CAP_MCU_POWER_STATE)
281
7.32k
      ){
282
7.24k
        start_new_task(boost::shared_ptr<SpinelNCPTask>(new SpinelNCPTaskWake(this, NilReturn())));
283
7.24k
      }
284
7.32k
    }
285
286
30.5k
    mTaskQueue.push_back(task);
287
30.5k
  }
288
30.5k
}
289
290
int
291
nl::wpantund::spinel_status_to_wpantund_status(int spinel_status)
292
200
{
293
200
  wpantund_status_t ret;
294
200
  switch (spinel_status) {
295
10
  case SPINEL_STATUS_ALREADY:
296
10
    ret = kWPANTUNDStatus_Already;
297
10
    break;
298
6
  case SPINEL_STATUS_BUSY:
299
6
    ret = kWPANTUNDStatus_Busy;
300
6
    break;
301
3
  case SPINEL_STATUS_IN_PROGRESS:
302
3
    ret = kWPANTUNDStatus_InProgress;
303
3
    break;
304
13
  case SPINEL_STATUS_JOIN_FAILURE:
305
13
    ret = kWPANTUNDStatus_JoinFailedUnknown;
306
13
    break;
307
1
  case SPINEL_STATUS_JOIN_INCOMPATIBLE:
308
1
    ret = kWPANTUNDStatus_JoinFailedAtScan;
309
1
    break;
310
1
  case SPINEL_STATUS_JOIN_SECURITY:
311
1
    ret = kWPANTUNDStatus_JoinFailedAtAuthenticate;
312
1
    break;
313
0
  case SPINEL_STATUS_OK:
314
0
    ret = kWPANTUNDStatus_Ok;
315
0
    break;
316
36
  case SPINEL_STATUS_PROP_NOT_FOUND:
317
36
    ret = kWPANTUNDStatus_PropertyNotFound;
318
36
    break;
319
6
  case SPINEL_STATUS_INVALID_ARGUMENT:
320
6
    ret = kWPANTUNDStatus_NCP_InvalidArgument;
321
6
    break;
322
1
  case SPINEL_STATUS_INVALID_STATE:
323
1
    ret = kWPANTUNDStatus_InvalidForCurrentState;
324
1
    break;
325
326
123
  default:
327
123
    ret = WPANTUND_NCPERROR_TO_STATUS(spinel_status);
328
123
    break;
329
200
  }
330
331
200
  return ret;
332
200
}
333
334
int
335
nl::wpantund::peek_ncp_callback_status(int event, va_list args)
336
35.7k
{
337
35.7k
  int ret = 0;
338
339
35.7k
  if (EVENT_NCP_PROP_VALUE_IS == event) {
340
8.59k
    va_list tmp;
341
8.59k
    va_copy(tmp, args);
342
8.59k
    unsigned int key = va_arg(tmp, unsigned int);
343
8.59k
    if (SPINEL_PROP_LAST_STATUS == key) {
344
2.19k
      const uint8_t* spinel_data_ptr = va_arg(tmp, const uint8_t*);
345
2.19k
      spinel_size_t spinel_data_len = va_arg(tmp, spinel_size_t);
346
347
2.19k
      if (spinel_datatype_unpack(spinel_data_ptr, spinel_data_len, "i", &ret) <= 0) {
348
1.95k
        ret = SPINEL_STATUS_PARSE_ERROR;
349
1.95k
      }
350
2.19k
    }
351
8.59k
    va_end(tmp);
352
27.1k
  } else if (EVENT_NCP_RESET == event) {
353
18
    va_list tmp;
354
18
    va_copy(tmp, args);
355
18
    ret = va_arg(tmp, int);
356
18
    va_end(tmp);
357
18
  }
358
359
35.7k
  return ret;
360
35.7k
}
361
362
SpinelNCPInstance::SpinelNCPInstance(const Settings& settings) :
363
14.3k
  NCPInstanceBase(settings), mControlInterface(this), mVendorCustom(this)
364
14.3k
{
365
14.3k
  mInboundFrameDataLen = 0;
366
14.3k
  mInboundFrameDataPtr = NULL;
367
14.3k
  mInboundFrameDataType = 0;
368
14.3k
  mInboundFrameHDLCCRC = 0;
369
14.3k
  mInboundFrameSize = 0;
370
14.3k
  mInboundHeader = 0;
371
14.3k
  mIsCommissioned = false;
372
14.3k
  mFilterRLOCAddresses = true;
373
14.3k
  mFilterALOCAddresses = true;
374
14.3k
  mTickleOnHostDidWake = false;
375
14.3k
  mIsPcapInProgress = false;
376
14.3k
  mLastHeader = 0;
377
14.3k
  mLastTID = 0;
378
14.3k
  mNetworkKeyIndex = 0;
379
14.3k
  mOutboundBufferEscapedLen = 0;
380
14.3k
  mOutboundBufferLen = 0;
381
14.3k
  mOutboundBufferSent = 0;
382
14.3k
  mOutboundBufferType = 0;
383
#if WPANTUND_NCP_RESET_EXPECTED_ON_START
384
  mResetIsExpected = true;
385
#else
386
14.3k
  mResetIsExpected = false;
387
14.3k
#endif
388
14.3k
  mSetSteeringDataWhenJoinable = false;
389
14.3k
  mSubPTIndex = 0;
390
14.3k
  mTXPower = 0;
391
14.3k
  mThreadMode = 0;
392
14.3k
  mXPANIDWasExplicitlySet = false;
393
14.3k
  mChannelManagerNewChannel = 0;
394
14.3k
  mMacFilterFixedRssi = -100;
395
14.3k
  mSupportedChannelMask = 0;
396
14.3k
  mPreferredChannelMask = 0;
397
14.3k
  mJoinerDiscernerBitLength = 0;
398
14.3k
  mCommissionerEnergyScanResult.clear();
399
14.3k
  mCommissionerPanIdConflictResult.clear();
400
401
14.3k
  mSettings.clear();
402
403
14.3k
  regsiter_all_get_handlers();
404
14.3k
  regsiter_all_set_handlers();
405
14.3k
  regsiter_all_insert_handlers();
406
14.3k
  regsiter_all_remove_handlers();
407
408
14.3k
  memset(mSteeringDataAddress, 0xff, sizeof(mSteeringDataAddress));
409
410
14.3k
  if (!settings.empty()) {
411
13.9k
    int status;
412
13.9k
    Settings::const_iterator iter;
413
414
36.4k
    for(iter = settings.begin(); iter != settings.end(); iter++) {
415
22.4k
      if (!NCPInstanceBase::setup_property_supported_by_class(iter->first)) {
416
12.9k
        status = static_cast<NCPControlInterface&>(get_control_interface())
417
12.9k
          .property_set_value(iter->first, iter->second);
418
419
12.9k
        if (status != 0 && status != kWPANTUNDStatus_InProgress) {
420
9.89k
          syslog(LOG_WARNING, "Attempt to set property \"%s\" failed with err %s", iter->first.c_str(), wpantund_status_to_cstr(status));
421
9.89k
        }
422
12.9k
      }
423
22.4k
    }
424
13.9k
  }
425
14.3k
}
426
427
SpinelNCPInstance::~SpinelNCPInstance()
428
13.9k
{
429
13.9k
}
430
431
std::string
432
SpinelNCPInstance::thread_mode_to_string(uint8_t mode)
433
2.85k
{
434
2.85k
  char c_string[400];
435
436
2.85k
  snprintf(
437
2.85k
    c_string,
438
2.85k
    sizeof(c_string),
439
2.85k
    "RxOnWhenIdle:%s FTD:%s FullNetData:%s SecDataReq:%s",
440
2.85k
    ((mode & SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE) != 0)     ? "yes" : "no",
441
2.85k
    ((mode & SPINEL_THREAD_MODE_FULL_THREAD_DEV) != 0)     ? "yes" : "no",
442
2.85k
    ((mode & SPINEL_THREAD_MODE_FULL_NETWORK_DATA) != 0)   ? "yes" : "no",
443
2.85k
    ((mode & SPINEL_THREAD_MODE_SECURE_DATA_REQUEST) != 0) ? "yes" : "no"
444
2.85k
  );
445
446
2.85k
  return c_string;
447
2.85k
}
448
449
uint8_t
450
SpinelNCPInstance::get_thread_mode(void)
451
0
{
452
0
  return mThreadMode;
453
0
}
454
455
bool
456
SpinelNCPInstance::setup_property_supported_by_class(const std::string& prop_name)
457
0
{
458
0
  return NCPInstanceBase::setup_property_supported_by_class(prop_name);
459
0
}
460
461
SpinelNCPControlInterface&
462
SpinelNCPInstance::get_control_interface()
463
2.63M
{
464
2.63M
  return mControlInterface;
465
2.63M
}
466
467
std::set<std::string>
468
SpinelNCPInstance::get_supported_property_keys()const
469
0
{
470
0
  std::set<std::string> properties (NCPInstanceBase::get_supported_property_keys());
471
472
0
  properties.insert(kWPANTUNDProperty_ConfigNCPDriverName);
473
0
  properties.insert(kWPANTUNDProperty_NCPChannel);
474
0
  properties.insert(kWPANTUNDProperty_NCPChannelMask);
475
0
  properties.insert(kWPANTUNDProperty_NCPPreferredChannelMask);
476
0
  properties.insert(kWPANTUNDProperty_NCPFrequency);
477
0
  properties.insert(kWPANTUNDProperty_NCPRSSI);
478
0
  properties.insert(kWPANTUNDProperty_NCPExtendedAddress);
479
0
  properties.insert(kWPANTUNDProperty_NCPCCAFailureRate);
480
0
  properties.insert(kWPANTUNDProperty_NCPCapabilities);
481
482
0
  if (mCapabilities.count(SPINEL_CAP_ROLE_SLEEPY)) {
483
0
    properties.insert(kWPANTUNDProperty_NCPSleepyPollInterval);
484
0
  }
485
486
0
  properties.insert(kWPANTUNDProperty_ThreadRLOC16);
487
0
  properties.insert(kWPANTUNDProperty_ThreadDeviceMode);
488
0
  properties.insert(kWPANTUNDProperty_ThreadRouterID);
489
0
  properties.insert(kWPANTUNDProperty_ThreadLeaderAddress);
490
0
  properties.insert(kWPANTUNDProperty_ThreadLeaderRouterID);
491
0
  properties.insert(kWPANTUNDProperty_ThreadLeaderWeight);
492
0
  properties.insert(kWPANTUNDProperty_ThreadLeaderLocalWeight);
493
0
  properties.insert(kWPANTUNDProperty_ThreadNetworkData);
494
0
  properties.insert(kWPANTUNDProperty_ThreadNetworkDataVersion);
495
0
  properties.insert(kWPANTUNDProperty_ThreadStableNetworkData);
496
0
  properties.insert(kWPANTUNDProperty_ThreadStableNetworkDataVersion);
497
0
  properties.insert(kWPANTUNDProperty_ThreadLeaderNetworkData);
498
0
  properties.insert(kWPANTUNDProperty_ThreadStableLeaderNetworkData);
499
0
  properties.insert(kWPANTUNDProperty_ThreadChildTable);
500
0
  properties.insert(kWPANTUNDProperty_ThreadChildTableAddresses);
501
0
  properties.insert(kWPANTUNDProperty_ThreadNeighborTable);
502
0
  properties.insert(kWPANTUNDProperty_ThreadChildTimeout);
503
0
  properties.insert(kWPANTUNDProperty_ThreadRouterTable);
504
0
  properties.insert(kWPANTUNDProperty_ThreadParent);
505
0
  properties.insert(kWPANTUNDProperty_ThreadOffMeshRoutes);
506
0
  properties.insert(kWPANTUNDProperty_NetworkPartitionId);
507
0
  properties.insert(kWPANTUNDProperty_ThreadRouterUpgradeThreshold);
508
0
  properties.insert(kWPANTUNDProperty_ThreadRouterDowngradeThreshold);
509
0
  properties.insert(kWPANTUNDProperty_ThreadActiveDataset);
510
0
  properties.insert(kWPANTUNDProperty_ThreadPendingDataset);
511
0
  properties.insert(kWPANTUNDProperty_ThreadAddressCacheTable);
512
0
  properties.insert(kWPANTUNDProperty_OpenThreadSupportedRadioLinks);
513
514
0
  if (mCapabilities.count(SPINEL_CAP_NET_THREAD_1_2)) {
515
0
    properties.insert(kWPANTUNDProperty_ThreadDomainName);
516
0
    properties.insert(kWPANTUNDProperty_ThreadBackboneRouterPrimary);
517
0
  }
518
519
0
  if (mCapabilities.count(SPINEL_CAP_THREAD_BACKBONE_ROUTER)) {
520
0
    properties.insert(kWPANTUNDProperty_ThreadBackboneRouterLocalState);
521
0
    properties.insert(kWPANTUNDProperty_ThreadBackboneRouterLocalConfig);
522
0
    properties.insert(kWPANTUNDProperty_ThreadBackboneRouterLocalJitter);
523
0
  }
524
525
0
  if (mCapabilities.count(SPINEL_CAP_ERROR_RATE_TRACKING)) {
526
0
    properties.insert(kWPANTUNDProperty_ThreadNeighborTableErrorRates);
527
0
  }
528
529
0
  if (mCapabilities.count(SPINEL_CAP_MULTI_RADIO)) {
530
0
    properties.insert(kWPANTUNDProperty_OpenThreadNeighborTableMultiRadioInfo);
531
0
  }
532
533
0
  if (mCapabilities.count(SPINEL_CAP_DUA)) {
534
0
    properties.insert(kWPANTUNDProperty_ThreadDUAInterfaceIdentifier);
535
0
  }
536
537
0
  if (mCapabilities.count(SPINEL_CAP_THREAD_COMMISSIONER)) {
538
0
    properties.insert(kWPANTUNDProperty_CommissionerState);
539
0
    properties.insert(kWPANTUNDProperty_CommissionerProvisioningUrl);
540
0
    properties.insert(kWPANTUNDProperty_CommissionerSessionId);
541
0
    properties.insert(kWPANTUNDProperty_CommissionerJoiners);
542
0
  }
543
544
0
  if (mCapabilities.count(SPINEL_CAP_THREAD_JOINER)) {
545
0
    properties.insert(kWPANTUNDProperty_JoinerState);
546
0
    properties.insert(kWPANTUNDProperty_JoinerDiscernerValue);
547
0
    properties.insert(kWPANTUNDProperty_JoinerDiscernerBitLength);
548
0
  }
549
550
0
  if (mCapabilities.count(SPINEL_CAP_POSIX)) {
551
0
    properties.insert(kWPANTUNDProperty_POSIXAppRCPVersion);
552
0
  }
553
554
0
  if (mCapabilities.count(SPINEL_CAP_COUNTERS)) {
555
0
    properties.insert(kWPANTUNDProperty_NCPCounterAllMac);
556
0
    properties.insert(kWPANTUNDProperty_NCPCounter_TX_IP_SEC_TOTAL);
557
0
    properties.insert(kWPANTUNDProperty_NCPCounter_TX_IP_INSEC_TOTAL);
558
0
    properties.insert(kWPANTUNDProperty_NCPCounter_TX_IP_DROPPED);
559
0
    properties.insert(kWPANTUNDProperty_NCPCounter_RX_IP_SEC_TOTAL);
560
0
    properties.insert(kWPANTUNDProperty_NCPCounter_RX_IP_INSEC_TOTAL);
561
0
    properties.insert(kWPANTUNDProperty_NCPCounter_RX_IP_DROPPED);
562
0
    properties.insert(kWPANTUNDProperty_NCPCounter_TX_SPINEL_TOTAL);
563
0
    properties.insert(kWPANTUNDProperty_NCPCounter_RX_SPINEL_TOTAL);
564
0
    properties.insert(kWPANTUNDProperty_NCPCounter_RX_SPINEL_ERR);
565
0
    properties.insert(kWPANTUNDProperty_NCPCounterThreadMle);
566
0
    properties.insert(kWPANTUNDProperty_NCPCounterAllIPv6);
567
0
  }
568
569
0
  if (mCapabilities.count(SPINEL_CAP_MAC_ALLOWLIST)) {
570
0
    properties.insert(kWPANTUNDProperty_MACAllowlistEnabled);
571
0
    properties.insert(kWPANTUNDProperty_MACAllowlistEntries);
572
0
    properties.insert(kWPANTUNDProperty_MACDenylistEnabled);
573
0
    properties.insert(kWPANTUNDProperty_MACDenylistEntries);
574
0
  }
575
576
0
  if (mCapabilities.count(SPINEL_CAP_JAM_DETECT)) {
577
0
    properties.insert(kWPANTUNDProperty_JamDetectionStatus);
578
0
    properties.insert(kWPANTUNDProperty_JamDetectionEnable);
579
0
    properties.insert(kWPANTUNDProperty_JamDetectionRssiThreshold);
580
0
    properties.insert(kWPANTUNDProperty_JamDetectionWindow);
581
0
    properties.insert(kWPANTUNDProperty_JamDetectionBusyPeriod);
582
0
    properties.insert(kWPANTUNDProperty_JamDetectionDebugHistoryBitmap);
583
0
  }
584
585
0
  if (mCapabilities.count(SPINEL_CAP_CHANNEL_MONITOR)) {
586
0
    properties.insert(kWPANTUNDProperty_ChannelMonitorSampleInterval);
587
0
    properties.insert(kWPANTUNDProperty_ChannelMonitorRssiThreshold);
588
0
    properties.insert(kWPANTUNDProperty_ChannelMonitorSampleWindow);
589
0
    properties.insert(kWPANTUNDProperty_ChannelMonitorSampleCount);
590
0
    properties.insert(kWPANTUNDProperty_ChannelMonitorChannelQuality);
591
0
  }
592
593
0
  if (mCapabilities.count(SPINEL_CAP_CHANNEL_MANAGER)) {
594
0
    properties.insert(kWPANTUNDProperty_ChannelManagerNewChannel);
595
0
    properties.insert(kWPANTUNDProperty_ChannelManagerDelay);
596
0
    properties.insert(kWPANTUNDProperty_ChannelManagerAutoSelectEnabled);
597
0
    properties.insert(kWPANTUNDProperty_ChannelManagerAutoSelectInterval);
598
0
    properties.insert(kWPANTUNDProperty_ChannelManagerSupportedChannelMask);
599
0
    properties.insert(kWPANTUNDProperty_ChannelManagerFavoredChannelMask);
600
0
  }
601
602
0
  if (mCapabilities.count(SPINEL_CAP_THREAD_TMF_PROXY)) {
603
0
    properties.insert(kWPANTUNDProperty_TmfProxyEnabled);
604
0
  }
605
606
0
  if (mCapabilities.count(SPINEL_CAP_NEST_LEGACY_INTERFACE)) {
607
0
    properties.insert(kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix);
608
0
  }
609
610
0
  if (mCapabilities.count(SPINEL_CAP_TIME_SYNC)) {
611
0
    properties.insert(kWPANTUNDProperty_TimeSync_NetworkTime);
612
0
    properties.insert(kWPANTUNDProperty_TimeSync_Period);
613
0
    properties.insert(kWPANTUNDProperty_TimeSync_XtalThreshold);
614
0
  }
615
616
0
  if (mCapabilities.count(SPINEL_CAP_THREAD_SERVICE)) {
617
0
    properties.insert(kWPANTUNDProperty_ThreadServices);
618
0
    properties.insert(kWPANTUNDProperty_ThreadLeaderServices);
619
0
  }
620
621
0
  if (mCapabilities.count(SPINEL_CAP_THREAD_CSL_RECEIVER)) {
622
0
    properties.insert(kWPANTUNDProperty_ThreadCslPeriod);
623
0
    properties.insert(kWPANTUNDProperty_ThreadCslTimeout);
624
0
    properties.insert(kWPANTUNDProperty_ThreadCslChannel);
625
0
  }
626
627
0
  if (mCapabilities.count(SPINEL_CAP_RADIO_COEX)) {
628
0
    properties.insert(kWPANTUNDProperty_NCPCoexEnable);
629
0
    properties.insert(kWPANTUNDProperty_NCPCoexMetrics);
630
0
  }
631
632
0
  if (mCapabilities.count(SPINEL_CAP_OPENTHREAD_LOG_METADATA)) {
633
0
    properties.insert(kWPANTUNDProperty_OpenThreadLogTimestampBase);
634
0
  }
635
636
0
  {
637
0
    const std::set<std::string> vendor_props(mVendorCustom.get_supported_property_keys());
638
0
    properties.insert(vendor_props.begin(), vendor_props.end());
639
0
  }
640
641
0
  return properties;
642
0
}
643
644
cms_t
645
SpinelNCPInstance::get_ms_to_next_event(void)
646
2.92M
{
647
2.92M
  cms_t cms = NCPInstanceBase::get_ms_to_next_event();
648
649
2.92M
  if (ncp_state_is_detached_from_ncp(get_ncp_state())) {
650
257
    return CMS_DISTANT_FUTURE;
651
257
  }
652
653
  // If the control protothread hasn't even started, set cms to zero.
654
2.92M
  if (0 == mControlPT.lc) {
655
9.16k
    cms = 0;
656
9.16k
  }
657
658
2.92M
  if (!mTaskQueue.empty()) {
659
615k
    int tmp_cms = mTaskQueue.front()->get_ms_to_next_event();
660
615k
    if (tmp_cms < cms) {
661
425k
      cms = tmp_cms;
662
425k
    }
663
615k
  }
664
665
2.92M
  if (cms > mVendorCustom.get_ms_to_next_event()) {
666
0
    cms = mVendorCustom.get_ms_to_next_event();
667
0
  }
668
669
2.92M
  if (cms < 0) {
670
0
    cms = 0;
671
0
  }
672
673
2.92M
  return cms;
674
2.92M
}
675
676
static void
677
convert_rloc16_to_router_id(CallbackWithStatusArg1 cb, int status, const boost::any& value)
678
0
{
679
0
  uint8_t router_id = 0;
680
681
0
  if (status == kWPANTUNDStatus_Ok) {
682
0
    uint16_t rloc16 = any_to_int(value);
683
0
    router_id = rloc16 >> 10;
684
0
  }
685
0
  cb(status, router_id);
686
0
}
687
688
689
690
static int
691
unpack_commissioner_state(const uint8_t *data_in, spinel_size_t data_len, boost::any& value)
692
970
{
693
970
  spinel_ssize_t len;
694
970
  uint8_t state;
695
970
  int ret = kWPANTUNDStatus_Ok;
696
697
970
  len = spinel_datatype_unpack(
698
970
    data_in,
699
970
    data_len,
700
970
    SPINEL_DATATYPE_UINT8_S,
701
970
    &state
702
970
  );
703
704
970
  if (len > 0) {
705
559
    switch (state) {
706
99
    case SPINEL_MESHCOP_COMMISSIONER_STATE_DISABLED:
707
99
      value = std::string(kWPANTUNDCommissionerState_Disabled);
708
99
      break;
709
199
    case SPINEL_MESHCOP_COMMISSIONER_STATE_PETITION:
710
199
      value = std::string(kWPANTUNDCommissionerState_Petition);
711
199
      break;
712
136
    case SPINEL_MESHCOP_COMMISSIONER_STATE_ACTIVE:
713
136
      value = std::string(kWPANTUNDCommissionerState_Active);
714
136
      break;
715
125
    default:
716
125
      ret = kWPANTUNDStatus_Failure;
717
125
      break;
718
559
    }
719
559
  } else {
720
411
    ret = kWPANTUNDStatus_Failure;
721
411
  }
722
723
970
  return ret;
724
970
}
725
726
static int
727
unpack_commissioner_joiners(const uint8_t *data_in, spinel_size_t data_len, boost::any &value)
728
0
{
729
0
  spinel_ssize_t len;
730
0
  std::list<std::string> result;
731
0
  char c_string[300];
732
0
  int ret = kWPANTUNDStatus_Ok;
733
734
0
  while (data_len > 0) {
735
0
    const uint8_t *joiner_info_in;
736
0
    spinel_size_t joiner_info_len;
737
0
    uint32_t joiner_timeout;
738
0
    const char *joiner_pskd;
739
0
    const spinel_eui64_t *joiner_eui64 = NULL;
740
0
    uint8_t discerner_bit_len;
741
0
    uint64_t discerner_value;
742
0
    bool any_joiner = false;
743
744
0
    len = spinel_datatype_unpack(
745
0
      data_in,
746
0
      data_len,
747
0
      SPINEL_DATATYPE_STRUCT_S(
748
0
        SPINEL_DATATYPE_DATA_WLEN_S // Joiner Info struct (empty or EUI64 or Discerner)
749
0
        SPINEL_DATATYPE_UINT32_S
750
0
        SPINEL_DATATYPE_UTF8_S
751
0
      ),
752
0
      &joiner_info_in, &joiner_info_len,
753
0
      &joiner_timeout,
754
0
      &joiner_pskd
755
0
    );
756
757
0
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
758
759
0
    data_in += len;
760
0
    data_len -= len;
761
762
0
    switch (joiner_info_len)
763
0
    {
764
0
    case 0:
765
0
      any_joiner = true;
766
0
      break;
767
768
0
    case sizeof(spinel_eui64_t):
769
0
      joiner_eui64 = (const spinel_eui64_t *)joiner_info_in;
770
0
      break;
771
772
0
    default:
773
0
      len = spinel_datatype_unpack(
774
0
        joiner_info_in,
775
0
        joiner_info_len,
776
0
        (
777
0
          SPINEL_DATATYPE_UINT8_S
778
0
          SPINEL_DATATYPE_UINT64_S
779
0
        ),
780
0
        &discerner_bit_len,
781
0
        &discerner_value
782
0
      );
783
0
      joiner_eui64 = NULL;
784
0
      break;
785
0
    }
786
787
0
    if (any_joiner) {
788
0
       snprintf(c_string, sizeof(c_string), "any joiner, psk:%s, timeout:%.2f", joiner_pskd, joiner_timeout/1000.0);
789
790
0
    } else if (joiner_eui64 != NULL) {
791
0
      snprintf(c_string, sizeof(c_string), "eui64:%02X%02X%02X%02X%02X%02X%02X%02X, psk:%s, timeout:%.2f",
792
0
        joiner_eui64->bytes[0], joiner_eui64->bytes[1], joiner_eui64->bytes[2], joiner_eui64->bytes[3],
793
0
        joiner_eui64->bytes[4], joiner_eui64->bytes[5], joiner_eui64->bytes[6], joiner_eui64->bytes[7],
794
0
        joiner_pskd, joiner_timeout/1000.0);
795
796
0
    } else {
797
0
      snprintf(c_string, sizeof(c_string), "discerner:%" PRIu64 ", bit-len:%d, psk:%s, timeout:%.2f",
798
0
           discerner_value, discerner_bit_len, joiner_pskd, joiner_timeout/1000.0);
799
0
    }
800
801
0
    result.push_back(std::string(c_string));
802
0
  }
803
804
0
  value = result;
805
806
0
bail:
807
0
  return ret;
808
0
}
809
810
811
static int
812
unpack_channel_mask(const uint8_t *data_in, spinel_size_t data_len, boost::any& value)
813
1.53k
{
814
1.53k
  spinel_ssize_t len;
815
1.53k
  uint32_t channel_mask = 0;
816
1.53k
  uint8_t channel = 0xff;
817
1.53k
  int ret = kWPANTUNDStatus_Ok;
818
819
2.39k
  while (data_len > 0)
820
1.16k
  {
821
1.16k
    len = spinel_datatype_unpack(
822
1.16k
      data_in,
823
1.16k
      data_len,
824
1.16k
      SPINEL_DATATYPE_UINT8_S,
825
1.16k
      &channel
826
1.16k
    );
827
828
1.16k
    if ((len <= 0) || (channel >= 32)) {
829
304
      ret = kWPANTUNDStatus_Failure;
830
304
      break;
831
304
    }
832
833
857
    channel_mask |= (1U << channel);
834
835
857
    data_in += len;
836
857
    data_len -= len;
837
857
  }
838
839
1.53k
  if (ret == kWPANTUNDStatus_Ok) {
840
1.22k
    value = channel_mask;
841
1.22k
  }
842
843
1.53k
  return ret;
844
1.53k
}
845
846
static int
847
unpack_mac_allowlist_entries(const uint8_t *data_in, spinel_size_t data_len, boost::any& value, bool as_val_map)
848
0
{
849
0
  spinel_ssize_t len;
850
0
  ValueMap entry;
851
0
  std::list<ValueMap> result_as_val_map;
852
0
  std::list<std::string> result_as_string;
853
0
  const spinel_eui64_t *eui64 = NULL;
854
0
  int8_t rssi = 0;
855
856
0
  int ret = kWPANTUNDStatus_Ok;
857
858
0
  while (data_len > 0)
859
0
  {
860
0
    len = spinel_datatype_unpack(
861
0
      data_in,
862
0
      data_len,
863
0
      SPINEL_DATATYPE_STRUCT_S(
864
0
        SPINEL_DATATYPE_EUI64_S   // Extended address
865
0
        SPINEL_DATATYPE_INT8_S    // Rssi
866
0
      ),
867
0
      &eui64,
868
0
      &rssi
869
0
    );
870
871
0
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
872
873
0
    if (as_val_map) {
874
0
      entry.clear();
875
0
      entry[kWPANTUNDValueMapKey_Allowlist_ExtAddress] = Data(eui64->bytes, sizeof(spinel_eui64_t));
876
877
0
      if (rssi != kWPANTUND_Allowlist_RssiOverrideDisabled) {
878
0
        entry[kWPANTUNDValueMapKey_Allowlist_Rssi] = rssi;
879
0
      }
880
881
0
      result_as_val_map.push_back(entry);
882
883
0
    } else {
884
0
      char c_string[500];
885
0
      int index;
886
887
0
      index = snprintf(c_string, sizeof(c_string), "%02X%02X%02X%02X%02X%02X%02X%02X",
888
0
               eui64->bytes[0], eui64->bytes[1], eui64->bytes[2], eui64->bytes[3],
889
0
               eui64->bytes[4], eui64->bytes[5], eui64->bytes[6], eui64->bytes[7]);
890
891
0
      if (rssi != kWPANTUND_Allowlist_RssiOverrideDisabled) {
892
0
        if (index >= 0 && index < sizeof(c_string)) {
893
0
          snprintf(c_string + index, sizeof(c_string) - index, "   fixed-rssi:%d", rssi);
894
0
        }
895
0
      }
896
897
0
      result_as_string.push_back(std::string(c_string));
898
0
    }
899
900
0
    data_len -= len;
901
0
    data_in += len;
902
0
  }
903
904
0
  if (as_val_map) {
905
0
    value = result_as_val_map;
906
0
  } else {
907
0
    value = result_as_string;
908
0
  }
909
910
0
bail:
911
0
  return ret;
912
0
}
913
914
static int
915
unpack_mac_denylist_entries(const uint8_t *data_in, spinel_size_t data_len, boost::any& value, bool as_val_map)
916
0
{
917
0
  spinel_ssize_t len;
918
0
  ValueMap entry;
919
0
  std::list<ValueMap> result_as_val_map;
920
0
  std::list<std::string> result_as_string;
921
0
  const spinel_eui64_t *eui64 = NULL;
922
923
0
  int ret = kWPANTUNDStatus_Ok;
924
925
0
  while (data_len > 0)
926
0
  {
927
0
    len = spinel_datatype_unpack(
928
0
      data_in,
929
0
      data_len,
930
0
      SPINEL_DATATYPE_STRUCT_S(
931
0
        SPINEL_DATATYPE_EUI64_S   // Extended address
932
0
      ),
933
0
      &eui64
934
0
    );
935
936
0
    if (len <= 0)
937
0
    {
938
0
      ret = kWPANTUNDStatus_Failure;
939
0
      break;
940
0
    }
941
942
0
    if (as_val_map) {
943
0
      entry.clear();
944
0
      entry[kWPANTUNDValueMapKey_Allowlist_ExtAddress] = Data(eui64->bytes, sizeof(spinel_eui64_t));
945
0
      result_as_val_map.push_back(entry);
946
947
0
    } else {
948
0
      char c_string[500];
949
0
      int index;
950
951
0
      index = snprintf(c_string, sizeof(c_string), "%02X%02X%02X%02X%02X%02X%02X%02X",
952
0
               eui64->bytes[0], eui64->bytes[1], eui64->bytes[2], eui64->bytes[3],
953
0
               eui64->bytes[4], eui64->bytes[5], eui64->bytes[6], eui64->bytes[7]);
954
955
0
      result_as_string.push_back(std::string(c_string));
956
0
    }
957
958
0
    data_len -= len;
959
0
    data_in += len;
960
0
  }
961
962
0
  if (ret == kWPANTUNDStatus_Ok) {
963
964
0
    if (as_val_map) {
965
0
      value = result_as_val_map;
966
0
    } else {
967
0
      value = result_as_string;
968
0
    }
969
0
  }
970
971
0
  return ret;
972
0
}
973
974
static int
975
unpack_channel_occupancy(const uint8_t *data_in, spinel_size_t data_len, boost::any& value, bool as_val_map)
976
0
{
977
0
  std::list<std::string> result_as_string;
978
0
  std::list<ValueMap> result_as_val_map;
979
0
  int ret = kWPANTUNDStatus_Ok;
980
981
0
  while (data_len > 0)
982
0
  {
983
0
    spinel_ssize_t len;
984
0
    uint8_t channel;
985
0
    uint16_t quality;
986
987
0
    len = spinel_datatype_unpack(
988
0
      data_in,
989
0
      data_len,
990
0
      SPINEL_DATATYPE_STRUCT_S(
991
0
        SPINEL_DATATYPE_UINT8_S         // Channel
992
0
        SPINEL_DATATYPE_UINT16_S        // Quality
993
0
      ),
994
0
      &channel,
995
0
      &quality
996
0
    );
997
998
0
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
999
1000
0
    if (!as_val_map) {
1001
0
      char c_string[100];
1002
1003
0
      snprintf(c_string, sizeof(c_string), "ch %d (0x%04x) %.2f%% busy ", channel, quality,
1004
0
        static_cast<double>(quality) * 100.0 / 0xffff);
1005
1006
0
      result_as_string.push_back(std::string(c_string));
1007
0
    } else {
1008
0
      ValueMap entry;
1009
1010
0
      entry[kWPANTUNDValueMapKey_ChannelMonitor_Channel] = boost::any((int)channel);
1011
0
      entry[kWPANTUNDValueMapKey_ChannelMonitor_Quality] = boost::any((int)quality);
1012
0
      result_as_val_map.push_back(entry);
1013
0
    }
1014
1015
0
    data_in += len;
1016
0
    data_len -= len;
1017
0
  }
1018
1019
0
  if (as_val_map) {
1020
0
    value = result_as_val_map;
1021
0
  } else {
1022
0
    value = result_as_string;
1023
0
  }
1024
1025
0
bail:
1026
0
  return ret;
1027
0
}
1028
1029
static int
1030
unpack_ncp_counters_all_mac(const uint8_t *data_in, spinel_size_t data_len, boost::any& value, bool as_val_map)
1031
0
{
1032
0
  std::list<std::string> result_as_string;
1033
0
  ValueMap result_as_val_map;
1034
0
  int ret = kWPANTUNDStatus_Ok;
1035
0
  spinel_ssize_t len;
1036
1037
0
  const char *tx_counter_names[] = {
1038
0
    kWPANTUNDValueMapKey_Counter_TxTotal,
1039
0
    kWPANTUNDValueMapKey_Counter_TxUnicast,
1040
0
    kWPANTUNDValueMapKey_Counter_TxBroadcast,
1041
0
    kWPANTUNDValueMapKey_Counter_TxAckRequested,
1042
0
    kWPANTUNDValueMapKey_Counter_TxAcked,
1043
0
    kWPANTUNDValueMapKey_Counter_TxNoAckRequested,
1044
0
    kWPANTUNDValueMapKey_Counter_TxData,
1045
0
    kWPANTUNDValueMapKey_Counter_TxDataPoll,
1046
0
    kWPANTUNDValueMapKey_Counter_TxBeacon,
1047
0
    kWPANTUNDValueMapKey_Counter_TxBeaconRequest,
1048
0
    kWPANTUNDValueMapKey_Counter_TxOther,
1049
0
    kWPANTUNDValueMapKey_Counter_TxRetry,
1050
0
    kWPANTUNDValueMapKey_Counter_TxErrCca,
1051
0
    kWPANTUNDValueMapKey_Counter_TxErrAbort,
1052
0
    kWPANTUNDValueMapKey_Counter_TxErrBusyChannel,
1053
0
    NULL
1054
0
  };
1055
1056
0
  const char *rx_counter_names[] = {
1057
0
    kWPANTUNDValueMapKey_Counter_RxTotal,
1058
0
    kWPANTUNDValueMapKey_Counter_RxUnicast,
1059
0
    kWPANTUNDValueMapKey_Counter_RxBroadcast,
1060
0
    kWPANTUNDValueMapKey_Counter_RxData,
1061
0
    kWPANTUNDValueMapKey_Counter_RxDataPoll,
1062
0
    kWPANTUNDValueMapKey_Counter_RxBeacon,
1063
0
    kWPANTUNDValueMapKey_Counter_RxBeaconRequest,
1064
0
    kWPANTUNDValueMapKey_Counter_RxOther,
1065
0
    kWPANTUNDValueMapKey_Counter_RxAddressFiltered,
1066
0
    kWPANTUNDValueMapKey_Counter_RxDestAddrFiltered,
1067
0
    kWPANTUNDValueMapKey_Counter_RxDuplicated,
1068
0
    kWPANTUNDValueMapKey_Counter_RxErrNoFrame,
1069
0
    kWPANTUNDValueMapKey_Counter_RxErrUnknownNeighbor,
1070
0
    kWPANTUNDValueMapKey_Counter_RxErrInvalidSrcAddr,
1071
0
    kWPANTUNDValueMapKey_Counter_RxErrSec,
1072
0
    kWPANTUNDValueMapKey_Counter_RxErrFcs,
1073
0
    kWPANTUNDValueMapKey_Counter_RxErrOther,
1074
0
    NULL
1075
0
  };
1076
1077
0
  for (int struct_index = 0; struct_index < 2; struct_index++)
1078
0
  {
1079
0
    const char **counter_names;
1080
0
    const uint8_t *struct_in = NULL;
1081
0
    unsigned int struct_len = 0;
1082
0
    spinel_size_t len;
1083
1084
0
    counter_names = (struct_index == 0) ? tx_counter_names : rx_counter_names;
1085
1086
0
    len = spinel_datatype_unpack(
1087
0
      data_in,
1088
0
      data_len,
1089
0
      SPINEL_DATATYPE_DATA_WLEN_S,
1090
0
      &struct_in,
1091
0
      &struct_len
1092
0
    );
1093
1094
0
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1095
1096
0
    data_in += len;
1097
0
    data_len -= len;
1098
1099
0
    while (*counter_names != NULL) {
1100
0
      uint32_t counter_value;
1101
1102
0
      len = spinel_datatype_unpack(
1103
0
        struct_in,
1104
0
        struct_len,
1105
0
        SPINEL_DATATYPE_UINT32_S,
1106
0
        &counter_value
1107
0
      );
1108
1109
0
      require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1110
1111
0
      struct_in  += len;
1112
0
      struct_len -= len;
1113
1114
0
      if (!as_val_map) {
1115
0
        char c_string[200];
1116
0
        snprintf(c_string, sizeof(c_string), "%-20s = %d", *counter_names, counter_value);
1117
0
        result_as_string.push_back(std::string(c_string));
1118
0
      } else {
1119
0
        result_as_val_map[*counter_names] = counter_value;
1120
0
      }
1121
1122
0
      counter_names++;
1123
0
    }
1124
0
  }
1125
1126
0
  if (as_val_map) {
1127
0
    value = result_as_val_map;
1128
0
  } else {
1129
0
    value = result_as_string;
1130
0
  }
1131
1132
0
bail:
1133
0
  return ret;
1134
0
}
1135
1136
static int
1137
unpack_ncp_counters_mle(const uint8_t *data_in, spinel_size_t data_len, boost::any& value, bool as_val_map)
1138
0
{
1139
0
  std::list<std::string> result_as_string;
1140
0
  ValueMap result_as_val_map;
1141
0
  int ret = kWPANTUNDStatus_Ok;
1142
0
  spinel_ssize_t len;
1143
1144
0
  const char *mle_counter_names[] = {
1145
0
    kWPANTUNDValueMapKey_MleCounter_DisabledRole,
1146
0
    kWPANTUNDValueMapKey_MleCounter_DetachedRole,
1147
0
    kWPANTUNDValueMapKey_MleCounter_ChildRole,
1148
0
    kWPANTUNDValueMapKey_MleCounter_RouterRole,
1149
0
    kWPANTUNDValueMapKey_MleCounter_LeaderRole,
1150
0
    kWPANTUNDValueMapKey_MleCounter_AttachAttempts,
1151
0
    kWPANTUNDValueMapKey_MleCounter_PartitionIdChanges,
1152
0
    kWPANTUNDValueMapKey_MleCounter_BetterPartitionAttaches,
1153
0
    kWPANTUNDValueMapKey_MleCounter_ParentChanges,
1154
0
    NULL
1155
0
  };
1156
1157
0
  const char **counter_names = mle_counter_names;
1158
1159
0
  while (*counter_names != NULL) {
1160
0
    uint16_t counter_value;
1161
1162
0
    len = spinel_datatype_unpack(
1163
0
      data_in,
1164
0
      data_len,
1165
0
      SPINEL_DATATYPE_UINT16_S,
1166
0
      &counter_value
1167
0
    );
1168
1169
0
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1170
1171
0
    data_in  += len;
1172
0
    data_len -= len;
1173
1174
0
    if (!as_val_map) {
1175
0
      char c_string[200];
1176
0
      snprintf(c_string, sizeof(c_string), "%-20s = %d", *counter_names, counter_value);
1177
0
      result_as_string.push_back(std::string(c_string));
1178
0
    } else {
1179
0
      result_as_val_map[*counter_names] = counter_value;
1180
0
    }
1181
1182
0
    counter_names++;
1183
0
  }
1184
1185
0
  if (as_val_map) {
1186
0
    value = result_as_val_map;
1187
0
  } else {
1188
0
    value = result_as_string;
1189
0
  }
1190
1191
0
bail:
1192
0
  return ret;
1193
0
}
1194
1195
static int
1196
unpack_ncp_counters_ipv6(const uint8_t *data_in, spinel_size_t data_len, boost::any& value, bool as_val_map)
1197
0
{
1198
0
  std::list<std::string> result_as_string;
1199
0
  ValueMap result_as_val_map;
1200
0
  int ret = kWPANTUNDStatus_Ok;
1201
0
  spinel_ssize_t len;
1202
1203
0
  const char *tx_counter_names[] = {
1204
0
    kWPANTUNDValueMapKey_IPv6Counter_TxSuccess,
1205
0
    kWPANTUNDValueMapKey_IPv6Counter_TxFailure,
1206
0
    NULL
1207
0
  };
1208
1209
0
  const char *rx_counter_names[] = {
1210
0
    kWPANTUNDValueMapKey_IPv6Counter_RxSuccess,
1211
0
    kWPANTUNDValueMapKey_IPv6Counter_RxFailure,
1212
0
    NULL
1213
0
  };
1214
1215
0
  for (int struct_index = 0; struct_index < 2; struct_index++)
1216
0
  {
1217
0
    const char **counter_names;
1218
0
    const uint8_t *struct_in = NULL;
1219
0
    unsigned int struct_len = 0;
1220
0
    spinel_size_t len;
1221
1222
0
    counter_names = (struct_index == 0) ? tx_counter_names : rx_counter_names;
1223
1224
0
    len = spinel_datatype_unpack(
1225
0
      data_in,
1226
0
      data_len,
1227
0
      SPINEL_DATATYPE_DATA_WLEN_S,
1228
0
      &struct_in,
1229
0
      &struct_len
1230
0
    );
1231
1232
0
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1233
1234
0
    data_in += len;
1235
0
    data_len -= len;
1236
1237
0
    while (*counter_names != NULL) {
1238
0
      uint32_t counter_value;
1239
1240
0
      len = spinel_datatype_unpack(
1241
0
        struct_in,
1242
0
        struct_len,
1243
0
        SPINEL_DATATYPE_UINT32_S,
1244
0
        &counter_value
1245
0
      );
1246
1247
0
      require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1248
1249
0
      struct_in  += len;
1250
0
      struct_len -= len;
1251
1252
0
      if (!as_val_map) {
1253
0
        char c_string[200];
1254
0
        snprintf(c_string, sizeof(c_string), "%-20s = %d", *counter_names, counter_value);
1255
0
        result_as_string.push_back(std::string(c_string));
1256
0
      } else {
1257
0
        result_as_val_map[*counter_names] = counter_value;
1258
0
      }
1259
1260
0
      counter_names++;
1261
0
    }
1262
0
  }
1263
1264
0
  if (as_val_map) {
1265
0
    value = result_as_val_map;
1266
0
  } else {
1267
0
    value = result_as_string;
1268
0
  }
1269
1270
0
bail:
1271
0
  return ret;
1272
0
}
1273
1274
static int
1275
unpack_coex_metrics(const uint8_t *data_in, spinel_size_t data_len, boost::any& value, bool as_val_map)
1276
0
{
1277
0
  std::list<std::string> result_as_string;
1278
0
  ValueMap result_as_val_map;
1279
0
  int ret = kWPANTUNDStatus_Ok;
1280
0
  spinel_ssize_t len;
1281
0
  bool stopped;
1282
0
  uint32_t num_grant_glitch;
1283
1284
0
  const char *tx_coex_metrics_names[] = {
1285
0
    kWPANTUNDValueMapKey_CoexMetrics_NumTxRequest,
1286
0
    kWPANTUNDValueMapKey_CoexMetrics_NumTxGrantImmediate,
1287
0
    kWPANTUNDValueMapKey_CoexMetrics_NumTxGrantWait,
1288
0
    kWPANTUNDValueMapKey_CoexMetrics_NumTxGrantWaitActivated,
1289
0
    kWPANTUNDValueMapKey_CoexMetrics_NumTxGrantWaitTimeout,
1290
0
    kWPANTUNDValueMapKey_CoexMetrics_NumTxGrantDeactivatedDuringRequest,
1291
0
    kWPANTUNDValueMapKey_CoexMetrics_NumTxDelayedGrant,
1292
0
    kWPANTUNDValueMapKey_CoexMetrics_AvgTxRequestToGrantTime,
1293
0
    NULL
1294
0
  };
1295
1296
0
  const char *rx_coex_metrics_names[] = {
1297
0
    kWPANTUNDValueMapKey_CoexMetrics_NumRxRequest,
1298
0
    kWPANTUNDValueMapKey_CoexMetrics_NumRxGrantImmediate,
1299
0
    kWPANTUNDValueMapKey_CoexMetrics_NumRxGrantWait,
1300
0
    kWPANTUNDValueMapKey_CoexMetrics_NumRxGrantWaitActivated,
1301
0
    kWPANTUNDValueMapKey_CoexMetrics_NumRxGrantWaitTimeout,
1302
0
    kWPANTUNDValueMapKey_CoexMetrics_NumRxGrantDeactivatedDuringRequest,
1303
0
    kWPANTUNDValueMapKey_CoexMetrics_NumRxDelayedGrant,
1304
0
    kWPANTUNDValueMapKey_CoexMetrics_AvgRxRequestToGrantTime,
1305
0
    kWPANTUNDValueMapKey_CoexMetrics_NumRxGrantNone,
1306
0
    NULL
1307
0
  };
1308
1309
0
  for (int index = 0; index < 2; index++)
1310
0
  {
1311
0
    const char **counter_names;
1312
0
    const uint8_t *struct_in = NULL;
1313
0
    unsigned int struct_len = 0;
1314
0
    spinel_size_t len;
1315
1316
0
    counter_names = (index == 0) ? tx_coex_metrics_names : rx_coex_metrics_names;
1317
1318
0
    len = spinel_datatype_unpack(
1319
0
      data_in,
1320
0
      data_len,
1321
0
      SPINEL_DATATYPE_DATA_WLEN_S,
1322
0
      &struct_in,
1323
0
      &struct_len
1324
0
    );
1325
1326
0
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1327
1328
0
    data_in += len;
1329
0
    data_len -= len;
1330
1331
0
    while (*counter_names != NULL) {
1332
0
      uint32_t counter_value;
1333
1334
0
      len = spinel_datatype_unpack(
1335
0
        struct_in,
1336
0
        struct_len,
1337
0
        SPINEL_DATATYPE_UINT32_S,
1338
0
        &counter_value
1339
0
      );
1340
1341
0
      require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1342
1343
0
      struct_in  += len;
1344
0
      struct_len -= len;
1345
1346
0
      if (!as_val_map) {
1347
0
        char c_string[200];
1348
0
        snprintf(c_string, sizeof(c_string), "%-20s = %u", *counter_names, counter_value);
1349
0
        result_as_string.push_back(std::string(c_string));
1350
0
      } else {
1351
0
        result_as_val_map[*counter_names] = counter_value;
1352
0
      }
1353
1354
0
      counter_names++;
1355
0
    }
1356
0
  }
1357
1358
0
  len = spinel_datatype_unpack(data_in, data_len, SPINEL_DATATYPE_BOOL_S, &stopped);
1359
0
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1360
0
  data_in += len;
1361
0
  data_len -= len;
1362
1363
0
  len = spinel_datatype_unpack(data_in, data_len, SPINEL_DATATYPE_UINT32_S, &num_grant_glitch);
1364
0
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1365
0
  data_in += len;
1366
0
  data_len -= len;
1367
1368
0
  if (!as_val_map) {
1369
0
    char c_string[200];
1370
0
    snprintf(c_string, sizeof(c_string), "%-20s = %u", kWPANTUNDValueMapKey_CoexMetrics_Stopped, stopped);
1371
0
    result_as_string.push_back(std::string(c_string));
1372
1373
0
    snprintf(c_string, sizeof(c_string), "%-20s = %u", kWPANTUNDValueMapKey_CoexMetrics_NumGrantGlitch, num_grant_glitch);
1374
0
    result_as_string.push_back(std::string(c_string));
1375
0
  } else {
1376
0
    result_as_val_map[kWPANTUNDValueMapKey_CoexMetrics_Stopped] = stopped;
1377
0
    result_as_val_map[kWPANTUNDValueMapKey_CoexMetrics_NumGrantGlitch] = num_grant_glitch;
1378
0
  }
1379
1380
0
  if (as_val_map) {
1381
0
    value = result_as_val_map;
1382
0
  } else {
1383
0
    value = result_as_string;
1384
0
  }
1385
1386
0
bail:
1387
0
  return ret;
1388
0
}
1389
1390
1391
static int
1392
unpack_mcu_power_state(const uint8_t *data_in, spinel_size_t data_len, boost::any& value)
1393
0
{
1394
0
  spinel_ssize_t len;
1395
0
  uint8_t power_state;
1396
0
  int ret = kWPANTUNDStatus_Ok;
1397
1398
0
  len = spinel_datatype_unpack(
1399
0
    data_in,
1400
0
    data_len,
1401
0
    SPINEL_DATATYPE_UINT8_S,
1402
0
    &power_state
1403
0
  );
1404
1405
0
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1406
1407
0
  switch (power_state)
1408
0
  {
1409
0
  case SPINEL_MCU_POWER_STATE_ON:
1410
0
    value = std::string(kWPANTUNDNCPMCUPowerState_On);
1411
0
    break;
1412
1413
0
  case SPINEL_MCU_POWER_STATE_LOW_POWER:
1414
0
    value = std::string(kWPANTUNDNCPMCUPowerState_LowPower);
1415
0
    break;
1416
1417
0
  case SPINEL_MCU_POWER_STATE_OFF:
1418
0
    value = std::string(kWPANTUNDNCPMCUPowerState_Off);
1419
0
    break;
1420
1421
0
  default:
1422
0
    value = std::string("unknown");
1423
0
    break;
1424
0
  }
1425
1426
0
bail:
1427
0
  return ret;
1428
0
}
1429
1430
static int
1431
unpack_parent_info(const uint8_t *data_in, spinel_size_t data_len, boost::any& value, bool as_val_map)
1432
0
{
1433
0
  std::string result_as_string;
1434
0
  ValueMap result_as_val_map;
1435
0
  int ret = kWPANTUNDStatus_Ok;
1436
0
  spinel_ssize_t len;
1437
0
  const spinel_eui64_t *eui64 = NULL;
1438
0
  uint16_t rloc16;
1439
0
  uint32_t age;
1440
0
  int8_t average_rssi;
1441
0
  int8_t last_rssi;
1442
0
  uint8_t lqin;
1443
0
  uint8_t lqout;
1444
1445
0
  len = spinel_datatype_unpack(
1446
0
    data_in,
1447
0
    data_len,
1448
0
    (
1449
0
      SPINEL_DATATYPE_EUI64_S         // EUI64 Address
1450
      SPINEL_DATATYPE_UINT16_S        // Rloc16
1451
      SPINEL_DATATYPE_UINT32_S        // Age
1452
      SPINEL_DATATYPE_INT8_S          // Average RSSI
1453
      SPINEL_DATATYPE_INT8_S          // Last RSSI
1454
      SPINEL_DATATYPE_UINT8_S         // LinkQuality In
1455
0
      SPINEL_DATATYPE_UINT8_S         // LinkQuality Out
1456
0
    ),
1457
0
    &eui64,
1458
0
    &rloc16,
1459
0
    &age,
1460
0
    &average_rssi,
1461
0
    &last_rssi,
1462
0
    &lqin,
1463
0
    &lqout
1464
0
  );
1465
1466
0
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1467
1468
0
  if (!as_val_map) {
1469
0
    char c_string[200];
1470
1471
0
    snprintf(c_string, sizeof(c_string),
1472
0
      "%02X%02X%02X%02X%02X%02X%02X%02X, "
1473
0
      "RLOC16:%04x, "
1474
0
      "Age:%u, "
1475
0
      "AveRssi:%d, "
1476
0
      "LastRssi:%d, "
1477
0
      "LQIn:%d, "
1478
0
      "LQOut:%d",
1479
0
      eui64->bytes[0], eui64->bytes[1], eui64->bytes[2], eui64->bytes[3],
1480
0
      eui64->bytes[4], eui64->bytes[5], eui64->bytes[6], eui64->bytes[7],
1481
0
      rloc16,
1482
0
      age,
1483
0
      average_rssi,
1484
0
      last_rssi,
1485
0
      lqin,
1486
0
      lqout
1487
0
    );
1488
1489
0
    value = std::string(c_string);
1490
1491
0
  } else {
1492
0
    ValueMap map;
1493
0
    uint64_t ext_addr;
1494
1495
0
    ext_addr  = (uint64_t) eui64->bytes[7];
1496
0
    ext_addr |= (uint64_t) eui64->bytes[6] << 8;
1497
0
    ext_addr |= (uint64_t) eui64->bytes[5] << 16;
1498
0
    ext_addr |= (uint64_t) eui64->bytes[4] << 24;
1499
0
    ext_addr |= (uint64_t) eui64->bytes[3] << 32;
1500
0
    ext_addr |= (uint64_t) eui64->bytes[2] << 40;
1501
0
    ext_addr |= (uint64_t) eui64->bytes[1] << 48;
1502
0
    ext_addr |= (uint64_t) eui64->bytes[0] << 56;
1503
1504
0
    map[kWPANTUNDValueMapKey_NetworkTopology_ExtAddress]    = boost::any(ext_addr);
1505
0
    map[kWPANTUNDValueMapKey_NetworkTopology_RLOC16]        = boost::any(rloc16);
1506
0
    map[kWPANTUNDValueMapKey_NetworkTopology_Age]           = boost::any(age);
1507
0
    map[kWPANTUNDValueMapKey_NetworkTopology_AverageRssi]   = boost::any(average_rssi);
1508
0
    map[kWPANTUNDValueMapKey_NetworkTopology_LastRssi]      = boost::any(last_rssi);
1509
0
    map[kWPANTUNDValueMapKey_NetworkTopology_LinkQualityIn] = boost::any(lqin);
1510
1511
0
    value = map;
1512
0
  }
1513
1514
0
bail:
1515
0
  return ret;
1516
0
}
1517
1518
static const char *
1519
cache_table_entry_state_to_string(uint8_t state)
1520
404
{
1521
404
  const char *str;
1522
1523
404
  switch (state)
1524
404
  {
1525
193
  case SPINEL_ADDRESS_CACHE_ENTRY_STATE_CACHED:
1526
193
    str = kWPANTUNDCacheTableEntryState_Cached;
1527
193
    break;
1528
40
  case SPINEL_ADDRESS_CACHE_ENTRY_STATE_SNOOPED:
1529
40
    str = kWPANTUNDCacheTableEntryState_Snooped;
1530
40
    break;
1531
16
  case SPINEL_ADDRESS_CACHE_ENTRY_STATE_QUERY:
1532
16
    str = kWPANTUNDCacheTableEntryState_Query;
1533
16
    break;
1534
44
  case SPINEL_ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY:
1535
44
    str = kWPANTUNDCacheTableEntryState_RetryQuery;
1536
44
    break;
1537
111
  default:
1538
111
    str = "unknown";
1539
111
    break;
1540
404
  }
1541
1542
404
  return str;
1543
404
}
1544
1545
static int
1546
unpack_address_cache_table(const uint8_t *data_in, spinel_size_t data_len, boost::any& value, bool as_val_map)
1547
1.28k
{
1548
1.28k
  std::list<std::string> result_as_string;
1549
1.28k
  std::list<ValueMap> result_as_val_map;
1550
1.28k
  int ret = kWPANTUNDStatus_Ok;
1551
1552
1.68k
  while (data_len > 0)
1553
1.02k
  {
1554
1.02k
    spinel_ssize_t len;
1555
1.02k
    struct in6_addr *target_address = NULL;
1556
1.02k
    uint16_t target_rloc16;
1557
1.02k
    uint8_t age;
1558
1.02k
    uint8_t state;
1559
1.02k
    bool valid_last_trans;
1560
1.02k
    uint32_t last_trans_time;
1561
1.02k
    struct in6_addr *ml_eid = NULL;
1562
1.02k
    bool can_evict;
1563
1.02k
    uint16_t timeout;
1564
1.02k
    uint16_t retry_delay;
1565
1.02k
    const uint8_t *cached_struct_in = NULL;
1566
1.02k
    unsigned int cached_struct_len = 0;
1567
1.02k
    const uint8_t *other_struct_in = NULL;
1568
1.02k
    unsigned int other_struct_len = 0;
1569
1570
1.02k
    len = spinel_datatype_unpack(
1571
1.02k
      data_in,
1572
1.02k
      data_len,
1573
1.02k
      SPINEL_DATATYPE_STRUCT_S(
1574
1.02k
        SPINEL_DATATYPE_IPv6ADDR_S    // Target address
1575
1.02k
        SPINEL_DATATYPE_UINT16_S      // RLOC16
1576
1.02k
        SPINEL_DATATYPE_UINT8_S       // Age
1577
1.02k
        SPINEL_DATATYPE_UINT8_S       // State
1578
1.02k
        SPINEL_DATATYPE_DATA_WLEN_S   // Cached struct info
1579
1.02k
        SPINEL_DATATYPE_DATA_WLEN_S   // Other struct info
1580
1.02k
      ),
1581
1.02k
      &target_address,
1582
1.02k
      &target_rloc16,
1583
1.02k
      &age,
1584
1.02k
      &state,
1585
1.02k
      &cached_struct_in, &cached_struct_len,
1586
1.02k
      &other_struct_in, &other_struct_len
1587
1.02k
    );
1588
1589
1.02k
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1590
1591
597
    data_in += len;
1592
597
    data_len -= len;
1593
1594
597
    if (state == SPINEL_ADDRESS_CACHE_ENTRY_STATE_CACHED) {
1595
1596
265
      len = spinel_datatype_unpack(
1597
265
        cached_struct_in,
1598
265
        cached_struct_len,
1599
265
        (
1600
265
          SPINEL_DATATYPE_BOOL_S      // Is Last Transaction Time valid?
1601
          SPINEL_DATATYPE_UINT32_S    // Last Transaction Time
1602
265
          SPINEL_DATATYPE_IPv6ADDR_S  // Mesh-local EID
1603
265
        ),
1604
265
        &valid_last_trans,
1605
265
        &last_trans_time,
1606
265
        &ml_eid
1607
265
      );
1608
1609
265
      require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1610
1611
332
    } else {
1612
1613
332
      len = spinel_datatype_unpack(
1614
332
        other_struct_in,
1615
332
        other_struct_len,
1616
332
        (
1617
332
          SPINEL_DATATYPE_BOOL_S      // Can evict?
1618
          SPINEL_DATATYPE_UINT16_S    // Timeout
1619
332
          SPINEL_DATATYPE_UINT16_S    // Retry delay
1620
332
        ),
1621
332
        &can_evict,
1622
332
        &timeout,
1623
332
        &retry_delay
1624
332
      );
1625
1626
332
      require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1627
332
    }
1628
1629
404
    if (!as_val_map) {
1630
404
      char c_string[500];
1631
404
      int index = 0;
1632
1633
404
      index += snprintf(
1634
404
        c_string + index, sizeof(c_string) - index,
1635
404
        "%s -> 0x%04x, Age:%d, State:%s",
1636
404
        in6_addr_to_string(*target_address).c_str(),
1637
404
        target_rloc16,
1638
404
        age,
1639
404
        cache_table_entry_state_to_string(state)
1640
404
      );
1641
1642
404
      if (state == SPINEL_ADDRESS_CACHE_ENTRY_STATE_CACHED) {
1643
193
        if (valid_last_trans) {
1644
159
          index += snprintf(
1645
159
            c_string + index, sizeof(c_string) - index,
1646
159
            ", LastTrans:%u, ML-EID:%s",
1647
159
            last_trans_time,
1648
159
            in6_addr_to_string(*ml_eid).c_str()
1649
159
          );
1650
159
        }
1651
211
      } else {
1652
211
        index += snprintf(
1653
211
          c_string + index, sizeof(c_string) - index,
1654
211
          ", CanEvict:%s, Timeout:%d, RetryDelay:%d",
1655
211
          can_evict ? "yes" : "no",
1656
211
          timeout,
1657
211
          retry_delay
1658
211
        );
1659
211
      }
1660
1661
404
      result_as_string.push_back(std::string(c_string));
1662
1663
404
    } else {
1664
0
      ValueMap entry;
1665
1666
0
      entry[kWPANTUNDValueMapKey_AddressCacheTable_Address] = boost::any(in6_addr_to_string(*target_address));
1667
0
      entry[kWPANTUNDValueMapKey_AddressCacheTable_RLOC16]  = boost::any(target_rloc16);
1668
0
      entry[kWPANTUNDValueMapKey_AddressCacheTable_Age]     = boost::any(age);
1669
0
      entry[kWPANTUNDValueMapKey_AddressCacheTable_State]   = boost::any(std::string(cache_table_entry_state_to_string(state)));
1670
1671
0
      if (state == SPINEL_ADDRESS_CACHE_ENTRY_STATE_CACHED) {
1672
0
        if (valid_last_trans) {
1673
0
          entry[kWPANTUNDValueMapKey_AddressCacheTable_LastTrans]    = boost::any(last_trans_time);
1674
0
          entry[kWPANTUNDValueMapKey_AddressCacheTable_MeshLocalEID] = boost::any(in6_addr_to_string(*ml_eid));
1675
0
        }
1676
0
      } else {
1677
0
        entry[kWPANTUNDValueMapKey_AddressCacheTable_CanEvict]   = boost::any(can_evict);
1678
0
        entry[kWPANTUNDValueMapKey_AddressCacheTable_Timeout]    = boost::any(timeout);
1679
0
        entry[kWPANTUNDValueMapKey_AddressCacheTable_RetryDelay] = boost::any(retry_delay);
1680
0
      }
1681
1682
0
      result_as_val_map.push_back(entry);
1683
0
    }
1684
404
  }
1685
1686
656
  if (as_val_map) {
1687
0
    value = result_as_val_map;
1688
656
  } else {
1689
656
    value = result_as_string;
1690
656
  }
1691
1692
1.28k
bail:
1693
1.28k
  return ret;
1694
656
}
1695
1696
static int
1697
unpack_supported_radio_links(const uint8_t *data_in, spinel_size_t data_len, boost::any &value)
1698
0
{
1699
0
  std::list<std::string> result;
1700
0
  int ret = kWPANTUNDStatus_Ok;
1701
1702
0
  while (data_len > 0) {
1703
0
    spinel_ssize_t len;
1704
0
    unsigned int value;
1705
1706
0
    len = spinel_packed_uint_decode(data_in, data_len, &value);
1707
0
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1708
1709
0
    data_in += len;
1710
0
    data_len -= len;
1711
1712
0
    result.push_back(std::string(spinel_radio_link_to_cstr(value)));
1713
0
  }
1714
1715
0
  value = result;
1716
1717
0
bail:
1718
0
  return ret;
1719
0
}
1720
static int
1721
unpack_neighbor_table_multi_radio_info(const uint8_t *data_in, spinel_size_t data_len, boost::any &value)
1722
0
{
1723
0
  int ret = kWPANTUNDStatus_Ok;
1724
0
  std::list<std::string> result;
1725
0
  char c_string[200];
1726
0
  int  index;
1727
1728
0
  while (data_len > 0) {
1729
0
    spinel_ssize_t len = 0;
1730
0
    const uint8_t *entry_data;
1731
0
    spinel_size_t entry_len;
1732
0
    const spinel_eui64_t *eui64 = NULL;
1733
0
    uint16_t rloc16;
1734
0
    bool first_radio;
1735
1736
0
    len = spinel_datatype_unpack(
1737
0
      data_in,
1738
0
      data_len,
1739
0
      SPINEL_DATATYPE_DATA_WLEN_S,
1740
0
      &entry_data,
1741
0
      &entry_len
1742
0
    );
1743
1744
0
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1745
1746
0
    data_in += len;
1747
0
    data_len -= len;
1748
1749
    // Parse the entry_data (which contains info about a neighbor)
1750
1751
0
    len = spinel_datatype_unpack(
1752
0
      entry_data,
1753
0
      entry_len,
1754
0
      (
1755
0
        SPINEL_DATATYPE_EUI64_S         // EUI64 Address
1756
0
        SPINEL_DATATYPE_UINT16_S        // Rloc16
1757
0
      ),
1758
0
      &eui64,
1759
0
      &rloc16
1760
0
    );
1761
1762
0
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1763
1764
0
    index = 0;
1765
1766
0
    index += snprintf(c_string + index, sizeof(c_string) - index,
1767
0
      "%02X%02X%02X%02X%02X%02X%02X%02X, RLOC16:%04x, Radios:[",
1768
0
      eui64->bytes[0], eui64->bytes[1], eui64->bytes[2], eui64->bytes[3],
1769
0
      eui64->bytes[4], eui64->bytes[5], eui64->bytes[6], eui64->bytes[7],
1770
0
      rloc16
1771
0
    );
1772
1773
0
    require_action(index < sizeof(c_string), bail, ret = kWPANTUNDStatus_Failure);
1774
1775
0
    entry_data += len;
1776
0
    entry_len -= len;
1777
1778
0
    first_radio = true;
1779
1780
0
    while (entry_len > 0) {
1781
0
      const uint8_t *struct_data;
1782
0
      spinel_size_t struct_len;
1783
0
      unsigned int radio;
1784
0
      uint8_t preference;
1785
1786
0
      len = spinel_datatype_unpack(
1787
0
        entry_data,
1788
0
        entry_len,
1789
0
        SPINEL_DATATYPE_DATA_WLEN_S,
1790
0
        &struct_data,
1791
0
        &struct_len
1792
0
      );
1793
1794
0
      require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1795
1796
0
      entry_data += len;
1797
0
      entry_len -= len;
1798
1799
      // Parse struct_data (contains info about a supported radio link type)
1800
1801
0
      len = spinel_datatype_unpack(
1802
0
        struct_data,
1803
0
        struct_len,
1804
0
        (
1805
0
          SPINEL_DATATYPE_UINT_PACKED_S   // Radio link
1806
0
          SPINEL_DATATYPE_UINT8_S         // Preference
1807
0
        ),
1808
0
        &radio,
1809
0
        &preference
1810
0
      );
1811
1812
0
      require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
1813
1814
0
      struct_data += len;
1815
0
      struct_len -= len;
1816
1817
0
      index += snprintf(c_string + index, sizeof(c_string) - index,
1818
0
        "%s%s(%d)",
1819
0
        first_radio ? "" : ", ",
1820
0
        spinel_radio_link_to_cstr(radio),
1821
0
        preference
1822
0
      );
1823
1824
0
      require_action(index < sizeof(c_string), bail, ret = kWPANTUNDStatus_Failure);
1825
0
      first_radio = false;
1826
0
    }
1827
1828
0
    index += snprintf(c_string + index, sizeof(c_string) - index, "]");
1829
0
    require_action(index < sizeof(c_string), bail, ret = kWPANTUNDStatus_Failure);
1830
1831
0
    result.push_back(std::string(c_string));
1832
0
  }
1833
1834
0
  value = result;
1835
1836
0
bail:
1837
0
  return ret;
1838
0
}
1839
1840
static int
1841
unpack_mesh_local_prefix(const uint8_t *data_in, spinel_size_t data_len, boost::any &value)
1842
0
{
1843
0
  spinel_ssize_t len;
1844
0
  struct in6_addr *addr;
1845
0
  uint8_t prefix_len;
1846
0
  int ret = kWPANTUNDStatus_Failure;
1847
1848
0
  len = spinel_datatype_unpack(
1849
0
    data_in,
1850
0
    data_len,
1851
0
    (
1852
0
      SPINEL_DATATYPE_IPv6ADDR_S
1853
0
      SPINEL_DATATYPE_UINT8_S
1854
0
    ),
1855
0
    &addr,
1856
0
    &prefix_len
1857
0
  );
1858
1859
0
  if (len > 0)
1860
0
  {
1861
0
    char str[10];
1862
0
    snprintf(str, sizeof(str), "/%d", prefix_len);
1863
1864
0
    value = boost::any(in6_addr_to_string(*addr) + std::string(str));
1865
0
    ret = kWPANTUNDStatus_Ok;
1866
0
  }
1867
1868
0
  return ret;
1869
0
}
1870
1871
static int
1872
unpack_dataset(const uint8_t *data_in, spinel_size_t data_len, boost::any &value, bool as_val_map)
1873
0
{
1874
0
  int ret = kWPANTUNDStatus_Ok;
1875
0
  ThreadDataset dataset;
1876
0
  ValueMap map;
1877
0
  std::list<std::string> list;
1878
1879
0
  ret = dataset.set_from_spinel_frame(data_in, data_len);
1880
0
  require_noerr(ret, bail);
1881
1882
0
  if (as_val_map) {
1883
0
    dataset.convert_to_valuemap(map);
1884
0
    value = map;
1885
0
  } else {
1886
0
    dataset.convert_to_string_list(list);
1887
0
    value = list;
1888
0
  }
1889
1890
0
bail:
1891
0
  return ret;
1892
0
}
1893
1894
static int
1895
unpack_server_leader_services_as_any(const uint8_t *data_in, spinel_size_t data_len, boost::any& value, bool as_val_map)
1896
0
{
1897
0
  int ret = kWPANTUNDStatus_Ok;
1898
0
  spinel_ssize_t len;
1899
0
  uint8_t service_id;
1900
0
  uint32_t enterprise_number;
1901
0
  const uint8_t *service_data;
1902
0
  spinel_size_t service_data_len;
1903
0
  bool stable;
1904
0
  const uint8_t *server_data;
1905
0
  spinel_size_t server_data_len;
1906
0
  uint16_t rloc16;
1907
0
  int num_service = 0;
1908
0
  char c_string[500];
1909
1910
0
  std::list<ValueMap> result_as_val_map_list;
1911
0
  std::list<std::string> result_as_string_list;
1912
1913
0
  while (data_len > 0) {
1914
0
    len = spinel_datatype_unpack(
1915
0
      data_in,
1916
0
      data_len,
1917
0
      SPINEL_DATATYPE_STRUCT_S(
1918
0
        SPINEL_DATATYPE_UINT8_S   // Service ID
1919
0
        SPINEL_DATATYPE_UINT32_S    // Enterprise Number
1920
0
        SPINEL_DATATYPE_DATA_WLEN_S // Service Data
1921
0
        SPINEL_DATATYPE_BOOL_S      // stable
1922
0
        SPINEL_DATATYPE_DATA_WLEN_S // Server Data
1923
0
        SPINEL_DATATYPE_UINT16_S    // RLOC
1924
0
      ),
1925
0
      &service_id,
1926
0
      &enterprise_number,
1927
0
      &service_data,
1928
0
      &service_data_len,
1929
0
      &stable,
1930
0
      &server_data,
1931
0
      &server_data_len,
1932
0
      &rloc16
1933
0
    );
1934
1935
0
    if (len <= 0) {
1936
0
      break;
1937
0
    }
1938
1939
0
    if (as_val_map) {
1940
0
      ValueMap result_as_val_map;
1941
0
      result_as_val_map[kWPANTUNDValueMapKey_Service_ServiceId] = service_id;
1942
0
      result_as_val_map[kWPANTUNDValueMapKey_Service_EnterpriseNumber] = enterprise_number;
1943
0
      result_as_val_map[kWPANTUNDValueMapKey_Service_ServiceData] = Data(service_data, service_data_len);
1944
0
      result_as_val_map[kWPANTUNDValueMapKey_Service_Stable] = stable;
1945
0
      result_as_val_map[kWPANTUNDValueMapKey_Service_ServerData] = Data(server_data, server_data_len);
1946
0
      result_as_val_map[kWPANTUNDValueMapKey_Service_RLOC16] = rloc16;
1947
0
      result_as_val_map_list.push_back(result_as_val_map);
1948
0
    } else {
1949
0
      snprintf(c_string, sizeof(c_string), "ServiceId:%01x, EnterpriseNumber:%u, Stable:%d, RLOC16:%04x", service_id, enterprise_number, stable, rloc16);
1950
0
      result_as_string_list.push_back(std::string(c_string));
1951
0
    }
1952
1953
0
    num_service++;
1954
1955
0
    data_in += len;
1956
0
    data_len -= len;
1957
0
  }
1958
1959
0
  if (as_val_map) {
1960
0
    value = result_as_val_map_list;
1961
0
  } else {
1962
0
    value = result_as_string_list;
1963
0
  }
1964
1965
0
  return ret;
1966
0
}
1967
1968
static int
1969
unpack_mcu_dua_interface_identifier(const uint8_t *data_in, spinel_size_t data_len, boost::any& value)
1970
0
{
1971
0
  std::string buff;
1972
0
  int ret = kWPANTUNDStatus_Ok;
1973
1974
0
  if (data_len == 0)
1975
0
  {
1976
    // When data_len == 0 an empty string will be returned.
1977
0
    value = buff;
1978
0
  }
1979
0
  else if (data_len == 8)
1980
0
  {
1981
0
    buff = std::string(data_len*2,0);
1982
0
    buff.resize(2 * data_len + 1);
1983
1984
0
    encode_data_into_string(data_in, data_len, &buff[0], buff.capacity(), 0);
1985
0
    value = buff;
1986
0
  }
1987
0
  else
1988
0
  {
1989
0
    ret = kWPANTUNDStatus_InvalidArgument;
1990
0
  }
1991
1992
0
  return ret;
1993
0
}
1994
1995
static int
1996
unpack_meshcop_joiner_state(const uint8_t *data_in, spinel_size_t data_len, boost::any &value)
1997
1.65k
{
1998
1.65k
  spinel_ssize_t len;
1999
1.65k
  uint8_t joiner_state;
2000
1.65k
  int ret = kWPANTUNDStatus_Ok;
2001
2002
1.65k
  len = spinel_datatype_unpack(
2003
1.65k
    data_in,
2004
1.65k
    data_len,
2005
1.65k
    SPINEL_DATATYPE_UINT8_S,
2006
1.65k
    &joiner_state
2007
1.65k
  );
2008
2009
1.65k
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
2010
2011
1.02k
  switch (joiner_state) {
2012
129
  case SPINEL_MESHCOP_JOINER_STATE_IDLE:
2013
129
    value = std::string(kWPANTUNDThreadJoinerState_Idle);
2014
129
    break;
2015
2016
263
  case SPINEL_MESHCOP_JOINER_STATE_DISCOVER:
2017
263
    value = std::string(kWPANTUNDThreadJoinerState_Discover);
2018
263
    break;
2019
2020
75
  case SPINEL_MESHCOP_JOINER_STATE_CONNECTING:
2021
75
    value = std::string(kWPANTUNDThreadJoinerState_Connecting);
2022
75
    break;
2023
2024
277
  case SPINEL_MESHCOP_JOINER_STATE_CONNECTED:
2025
277
    value = std::string(kWPANTUNDThreadJoinerState_Connected);
2026
277
    break;
2027
2028
73
  case SPINEL_MESHCOP_JOINER_STATE_ENTRUST:
2029
73
    value = std::string(kWPANTUNDThreadJoinerState_Entrust);
2030
73
    break;
2031
2032
80
  case SPINEL_MESHCOP_JOINER_STATE_JOINED:
2033
80
    value = std::string(kWPANTUNDThreadJoinerState_Joined);
2034
80
    break;
2035
2036
128
  default:
2037
128
    value = std::string("unknown");
2038
128
    break;
2039
1.02k
  }
2040
2041
1.65k
bail:
2042
1.65k
  return ret;
2043
1.02k
}
2044
2045
static int
2046
unpack_meshcop_joiner_discerner_value(const uint8_t *data_in, spinel_size_t data_len, boost::any &value)
2047
0
{
2048
0
  spinel_ssize_t len;
2049
0
  uint8_t discerner_len;
2050
0
  uint64_t discerner_value = 0;
2051
0
  int ret = kWPANTUNDStatus_Ok;
2052
2053
0
  len = spinel_datatype_unpack(
2054
0
    data_in,
2055
0
    data_len,
2056
0
    SPINEL_DATATYPE_UINT8_S,
2057
0
    &discerner_len
2058
0
  );
2059
2060
0
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
2061
2062
0
  if (discerner_len != 0) {
2063
0
    data_in += len;
2064
0
    data_len -= len;
2065
2066
0
    len = spinel_datatype_unpack(
2067
0
      data_in,
2068
0
      data_len,
2069
0
      SPINEL_DATATYPE_UINT64_S,
2070
0
      &discerner_value
2071
0
    );
2072
0
  }
2073
2074
0
  value = discerner_value;
2075
2076
0
bail:
2077
0
  return ret;
2078
0
}
2079
2080
static int
2081
unpack_thread_network_time_spinel(const uint8_t *data_in, spinel_size_t data_len, uint64_t &time, int8_t &time_sync_status)
2082
489
{
2083
489
  return spinel_datatype_unpack(
2084
489
    data_in,
2085
489
    data_len,
2086
489
    (
2087
489
      SPINEL_DATATYPE_UINT64_S   // time
2088
489
      SPINEL_DATATYPE_INT8_S     // time sync status
2089
489
    ),
2090
489
    &time,
2091
489
    &time_sync_status
2092
489
  );
2093
489
}
2094
2095
static int
2096
unpack_thread_network_time_as_string(const uint8_t *data_in, spinel_size_t data_len, std::string &result)
2097
135
{
2098
135
  spinel_ssize_t len;
2099
135
  uint64_t time;
2100
135
  int8_t time_sync_status;
2101
135
  char c_string[500];
2102
135
  int ret = kWPANTUNDStatus_Failure;
2103
2104
135
  len = unpack_thread_network_time_spinel(data_in, data_len, time, time_sync_status);
2105
2106
135
  if (len > 0)
2107
135
  {
2108
135
    ret = kWPANTUNDStatus_Ok;
2109
135
    snprintf(c_string, sizeof(c_string), "ThreadNetworkTime: %" PRIu64 ", TimeSyncStatus:%d", time, time_sync_status);
2110
135
    result.assign(c_string);
2111
135
  }
2112
2113
135
  return ret;
2114
135
}
2115
2116
static int
2117
unpack_thread_network_time_as_valmap(const uint8_t *data_in, spinel_size_t data_len, ValueMap &result)
2118
354
{
2119
354
  spinel_ssize_t len;
2120
354
  ValueMap entry;
2121
354
  uint64_t time;
2122
354
  int8_t time_sync_status;
2123
354
  int ret = kWPANTUNDStatus_Failure;
2124
2125
354
  len = unpack_thread_network_time_spinel(data_in, data_len, time, time_sync_status);
2126
2127
354
  if (len > 0)
2128
135
  {
2129
135
    ret = kWPANTUNDStatus_Ok;
2130
135
    result.clear();
2131
135
    result[kWPANTUNDValueMapKey_TimeSync_Time] = time;
2132
135
    result[kWPANTUNDValueMapKey_TimeSync_Status] = time_sync_status;
2133
#if APPEND_NETWORK_TIME_RECEIVED_MONOTONIC_TIMESTAMP
2134
    result[kWPANTUNDValueMapKey_TimeSync_ReceivedMonoTimeUs] = time_get_monotonic_us();
2135
#endif // APPEND_NETWORK_TIME_RECEIVED_MONOTONIC_TIMESTAMP
2136
135
  }
2137
2138
354
  return ret;
2139
354
}
2140
2141
static int
2142
unpack_thread_network_time_as_any(const uint8_t *data_in, spinel_size_t data_len, boost::any& value, bool as_val_map)
2143
0
{
2144
0
  ValueMap result_as_val_map;
2145
0
  std::list<ValueMap> result_as_val_map_list;
2146
0
  std::string result_as_string;
2147
0
  std::list<std::string> result_as_string_list;
2148
0
  int ret;
2149
2150
0
  if (as_val_map)
2151
0
  {
2152
0
    ret = unpack_thread_network_time_as_valmap(data_in, data_len, result_as_val_map);
2153
2154
0
    if (ret == kWPANTUNDStatus_Ok)
2155
0
    {
2156
0
      result_as_val_map_list.push_back(result_as_val_map);
2157
0
      value = result_as_val_map_list;
2158
0
    }
2159
0
  }
2160
0
  else
2161
0
  {
2162
0
    ret = unpack_thread_network_time_as_string(data_in, data_len, result_as_string);
2163
2164
0
    if (ret == kWPANTUNDStatus_Ok)
2165
0
    {
2166
0
      result_as_string_list.push_back(result_as_string);
2167
0
      value = result_as_string_list;
2168
0
    }
2169
0
  }
2170
2171
0
  return ret;
2172
0
}
2173
2174
static int
2175
unpack_link_metrics_as_val_map(const uint8_t *data_in, spinel_size_t data_len, ValueMap &val_map)
2176
993
{
2177
993
  spinel_ssize_t len;
2178
993
  uint8_t metric_type;
2179
993
  uint8_t *metric_ptr = NULL;
2180
993
  uint32_t metric_len = 0;
2181
993
  int ret = kWPANTUNDStatus_Failure;
2182
2183
3.28k
  while (data_len > 0) {
2184
2.70k
    len = spinel_datatype_unpack(
2185
2.70k
      data_in,
2186
2.70k
      data_len,
2187
2.70k
      (
2188
2.70k
        SPINEL_DATATYPE_STRUCT_S(
2189
2.70k
          SPINEL_DATATYPE_UINT8_S
2190
2.70k
          SPINEL_DATATYPE_DATA_S
2191
2.70k
        )
2192
2.70k
      ),
2193
2.70k
      &metric_type,
2194
2.70k
      &metric_ptr,
2195
2.70k
      &metric_len
2196
2.70k
    );
2197
2198
2.70k
    require(len >= 0, bail);
2199
2.43k
    data_in += len;
2200
2.43k
    data_len -= len;
2201
2202
2.43k
    switch (metric_type) {
2203
524
    case SPINEL_THREAD_LINK_METRIC_PDU_COUNT:
2204
524
      val_map[kWPANTUNDValueMapKey_LinkMetrics_PDUCount] = *reinterpret_cast<uint32_t*>(metric_ptr);
2205
524
      break;
2206
601
    case SPINEL_THREAD_LINK_METRIC_LQI:
2207
601
      val_map[kWPANTUNDValueMapKey_LinkMetrics_LQI] = static_cast<uint32_t>(*reinterpret_cast<uint8_t*>(metric_ptr));
2208
601
      break;
2209
295
    case SPINEL_THREAD_LINK_METRIC_LINK_MARGIN:
2210
295
      val_map[kWPANTUNDValueMapKey_LinkMetrics_LinkMargin] = static_cast<uint32_t>(*reinterpret_cast<uint8_t*>(metric_ptr));
2211
295
      break;
2212
876
    case SPINEL_THREAD_LINK_METRIC_RSSI:
2213
876
      val_map[kWPANTUNDValueMapKey_LinkMetrics_RSSI] = *reinterpret_cast<int8_t*>(metric_ptr);
2214
876
      break;
2215
142
    default:
2216
142
      goto bail;
2217
2.43k
    }
2218
2.43k
  }
2219
2220
580
  ret = kWPANTUNDStatus_Ok;
2221
2222
993
bail:
2223
993
  return ret;
2224
580
}
2225
2226
static int
2227
unpack_backbone_router_primary(const uint8_t *data_in, spinel_size_t data_len, boost::any& value)
2228
0
{
2229
0
  spinel_ssize_t len;
2230
0
  char c_string[300];
2231
0
  int ret = kWPANTUNDStatus_Ok;
2232
0
  uint16_t server = 0;
2233
0
  uint16_t delay = 0;
2234
0
  uint32_t timeout = 0;
2235
0
  uint8_t seqno = 0;
2236
2237
0
  len = spinel_datatype_unpack(
2238
0
    data_in,
2239
0
    data_len,
2240
0
    (
2241
0
      SPINEL_DATATYPE_UINT16_S
2242
0
      SPINEL_DATATYPE_UINT16_S
2243
0
      SPINEL_DATATYPE_UINT32_S
2244
0
      SPINEL_DATATYPE_UINT8_S
2245
0
    ),
2246
0
    &server,
2247
0
    &delay,
2248
0
    &timeout,
2249
0
    &seqno
2250
0
  );
2251
2252
0
  if (len > 0) {
2253
0
    snprintf(c_string, sizeof(c_string), "server16 = 0x%04X, seqno = %hu, delay = %hu secs, timeout = %u secs",
2254
0
      server, (uint16_t)seqno, delay, timeout);
2255
2256
0
    value = std::string(c_string);
2257
0
  } else {
2258
0
    ret = kWPANTUNDStatus_Failure;
2259
0
  }
2260
2261
0
  return ret;
2262
0
}
2263
2264
static int
2265
unpack_backbone_router_config(const uint8_t *data_in, spinel_size_t data_len, boost::any& value)
2266
0
{
2267
0
  spinel_ssize_t len;
2268
0
  char c_string[300];
2269
0
  int ret = kWPANTUNDStatus_Ok;
2270
0
  uint16_t delay = 0;
2271
0
  uint32_t timeout = 0;
2272
0
  uint8_t seqno = 0;
2273
2274
0
  len = spinel_datatype_unpack(
2275
0
    data_in,
2276
0
    data_len,
2277
0
    (
2278
0
      SPINEL_DATATYPE_UINT16_S
2279
0
      SPINEL_DATATYPE_UINT32_S
2280
0
      SPINEL_DATATYPE_UINT8_S
2281
0
    ),
2282
0
    &delay,
2283
0
    &timeout,
2284
0
    &seqno
2285
0
  );
2286
2287
0
  if (len > 0) {
2288
0
    snprintf(c_string, sizeof(c_string), "seqno = %hu, delay = %hu secs, timeout = %u secs",
2289
0
      (uint16_t)seqno, delay, timeout);
2290
2291
0
    value = std::string(c_string);
2292
0
  } else {
2293
0
    ret = kWPANTUNDStatus_Failure;
2294
0
  }
2295
2296
0
  return ret;
2297
0
}
2298
2299
static int
2300
unpack_backbone_router_state(const uint8_t *data_in, spinel_size_t data_len, boost::any& value)
2301
0
{
2302
0
  spinel_ssize_t len;
2303
0
  uint8_t state;
2304
0
  int ret = kWPANTUNDStatus_Ok;
2305
2306
0
  len = spinel_datatype_unpack(
2307
0
    data_in,
2308
0
    data_len,
2309
0
    SPINEL_DATATYPE_UINT8_S,
2310
0
    &state
2311
0
  );
2312
2313
0
  if (len > 0) {
2314
0
    switch (state) {
2315
0
    case SPINEL_THREAD_BACKBONE_ROUTER_STATE_DISABLED:
2316
0
      value = std::string(kWPANTUNDThreadBackboneRouterState_Disabled);
2317
0
      break;
2318
0
    case SPINEL_THREAD_BACKBONE_ROUTER_STATE_SECONDARY:
2319
0
      value = std::string(kWPANTUNDThreadBackboneRouterState_Secondary);
2320
0
      break;
2321
0
    case SPINEL_THREAD_BACKBONE_ROUTER_STATE_PRIMARY:
2322
0
      value = std::string(kWPANTUNDThreadBackboneRouterState_Primary);
2323
0
      break;
2324
0
    default:
2325
0
      ret = kWPANTUNDStatus_Failure;
2326
0
      break;
2327
0
    }
2328
0
  } else {
2329
0
    ret = kWPANTUNDStatus_Failure;
2330
0
  }
2331
2332
0
  return ret;
2333
0
}
2334
2335
void
2336
SpinelNCPInstance::get_dataset_command_help(std::list<std::string> &list)
2337
0
{
2338
0
  list.clear();
2339
0
  list.push_back("List of valid commands:");
2340
0
  list.push_back("   - `" kWPANTUNDDatasetCommand_Erase "`: Erase the local Dataset (all fields are un-set)");
2341
0
  list.push_back("   - `" kWPANTUNDDatasetCommand_GetActive "`: Get the NCP's Active Operational Dataset and populate the local Dataset from it");
2342
0
  list.push_back("   - `" kWPANTUNDDatasetCommand_SetActive "`: Set the NCP's Active Operational Dataset from the current local Dataset");
2343
0
  list.push_back("   - `" kWPANTUNDDatasetCommand_SendMgmtGetActive "`: Send MGMT_GET_ACTIVE meshcop command requesting TLVs in current local Dataset");
2344
0
  list.push_back("   - `" kWPANTUNDDatasetCommand_SendMgmtSetActive "`: Send MGMT_SET_ACTIVE meshcop command along with the current local Dataset");
2345
0
  list.push_back("   - `" kWPANTUNDDatasetCommand_GetPending "`: Get the NCP's Pending Operational Dataset and populate the local DataSet from it");
2346
0
  list.push_back("   - `" kWPANTUNDDatasetCommand_SetPending "`: Set the NCP's Pending Operational Dataset from the current local Dataset");
2347
0
  list.push_back("   - `" kWPANTUNDDatasetCommand_SendMgmtGetPending "`: Send MGMT_GET_PENDING meshcop command requesting TLVs in the current local Dataset");
2348
0
  list.push_back("   - `" kWPANTUNDDatasetCommand_SendMgmtSetPending "`: Send MGMT_SET_PENDING meshcop command along with the current local Dataset");
2349
0
}
2350
2351
int
2352
SpinelNCPInstance::unpack_and_set_local_dataset(const uint8_t *data_in, spinel_size_t data_len)
2353
0
{
2354
0
  return mLocalDataset.set_from_spinel_frame(data_in, data_len);
2355
0
}
2356
2357
void
2358
SpinelNCPInstance::perform_dataset_command(const std::string &command, CallbackWithStatus cb)
2359
1.35k
{
2360
1.35k
  if (strcaseequal(command.c_str(), kWPANTUNDDatasetCommand_Erase)) {
2361
1
    mLocalDataset.clear();
2362
1
    cb(kWPANTUNDStatus_Ok);
2363
2364
1.35k
  } else if (strcaseequal(command.c_str(), kWPANTUNDDatasetCommand_GetActive)) {
2365
1
    get_spinel_prop_with_unpacker(
2366
1
      boost::bind(cb, _1),
2367
1
      SPINEL_PROP_THREAD_ACTIVE_DATASET,
2368
1
      boost::bind(&SpinelNCPInstance::unpack_and_set_local_dataset, this, _1, _2));
2369
2370
1.35k
  } else if (strcaseequal(command.c_str(), kWPANTUNDDatasetCommand_SetActive)) {
2371
119
    Data frame;
2372
119
    mLocalDataset.convert_to_spinel_frame(frame);
2373
119
    set_spinel_prop(frame, cb, SPINEL_PROP_THREAD_ACTIVE_DATASET, SPINEL_DATATYPE_DATA_C);
2374
2375
1.23k
  } else if (strcaseequal(command.c_str(), kWPANTUNDDatasetCommand_SendMgmtGetActive)) {
2376
122
    Data frame;
2377
122
    mLocalDataset.convert_to_spinel_frame(frame, /* include_values */ false);
2378
122
    set_spinel_prop(frame, cb, SPINEL_PROP_THREAD_MGMT_GET_ACTIVE_DATASET, SPINEL_DATATYPE_DATA_C);
2379
2380
1.11k
  } else if (strcaseequal(command.c_str(), kWPANTUNDDatasetCommand_SendMgmtSetActive)) {
2381
33
    Data frame;
2382
33
    mLocalDataset.convert_to_spinel_frame(frame);
2383
33
    set_spinel_prop(frame, cb, SPINEL_PROP_THREAD_MGMT_SET_ACTIVE_DATASET, SPINEL_DATATYPE_DATA_C);
2384
2385
1.08k
  } else if (strcaseequal(command.c_str(), kWPANTUNDDatasetCommand_GetPending)) {
2386
4
    get_spinel_prop_with_unpacker(
2387
4
      boost::bind(cb, _1),
2388
4
      SPINEL_PROP_THREAD_PENDING_DATASET,
2389
4
      boost::bind(&SpinelNCPInstance::unpack_and_set_local_dataset, this, _1, _2));
2390
2391
1.07k
  } else if (strcaseequal(command.c_str(), kWPANTUNDDatasetCommand_SetPending)) {
2392
437
    Data frame;
2393
437
    mLocalDataset.convert_to_spinel_frame(frame);
2394
437
    set_spinel_prop(frame, cb, SPINEL_PROP_THREAD_PENDING_DATASET, SPINEL_DATATYPE_DATA_C);
2395
2396
639
  } else if (strcaseequal(command.c_str(), kWPANTUNDDatasetCommand_SendMgmtGetPending)) {
2397
7
    Data frame;
2398
7
    mLocalDataset.convert_to_spinel_frame(frame, /* include_values */ false);
2399
7
    set_spinel_prop(frame, cb, SPINEL_PROP_THREAD_MGMT_GET_PENDING_DATASET, SPINEL_DATATYPE_DATA_C);
2400
2401
632
  } else if (strcaseequal(command.c_str(), kWPANTUNDDatasetCommand_SendMgmtSetPending)) {
2402
11
    Data frame;
2403
11
    mLocalDataset.convert_to_spinel_frame(frame);
2404
11
    set_spinel_prop(frame, cb, SPINEL_PROP_THREAD_MGMT_SET_PENDING_DATASET, SPINEL_DATATYPE_DATA_C);
2405
2406
621
  } else {
2407
621
    cb(kWPANTUNDStatus_InvalidArgument);
2408
621
  }
2409
1.35k
}
2410
2411
void
2412
SpinelNCPInstance::update_node_type(NodeType new_node_type)
2413
3.74k
{
2414
3.74k
  if (mNodeType != new_node_type) {
2415
1.75k
    syslog(
2416
1.75k
      LOG_NOTICE,
2417
1.75k
      "Node type change: \"%s\" -> \"%s\"",
2418
1.75k
      node_type_to_string(mNodeType).c_str(),
2419
1.75k
      node_type_to_string(new_node_type).c_str()
2420
1.75k
    );
2421
2422
1.75k
    mNodeType = new_node_type;
2423
1.75k
    signal_property_changed(kWPANTUNDProperty_NetworkNodeType, node_type_to_string(mNodeType));
2424
1.75k
  }
2425
3.74k
}
2426
2427
void
2428
SpinelNCPInstance::update_link_local_address(struct in6_addr *addr)
2429
439
{
2430
439
  if (NULL != addr
2431
322
    && (0 != memcmp(mNCPLinkLocalAddress.s6_addr, addr->s6_addr, sizeof(mNCPLinkLocalAddress)))
2432
439
  ) {
2433
151
    memcpy((void*)mNCPLinkLocalAddress.s6_addr, (void*)addr->s6_addr, sizeof(mNCPLinkLocalAddress));
2434
151
    signal_property_changed(kWPANTUNDProperty_IPv6LinkLocalAddress, in6_addr_to_string(*addr));
2435
151
  }
2436
439
}
2437
2438
void
2439
SpinelNCPInstance::update_mesh_local_address(struct in6_addr *addr)
2440
1.15k
{
2441
1.15k
  if (addr
2442
984
   && buffer_is_nonzero(addr->s6_addr, 8)
2443
878
   && (0 != memcmp(mNCPMeshLocalAddress.s6_addr, addr->s6_addr, sizeof(mNCPMeshLocalAddress)))
2444
1.15k
  ) {
2445
775
    memcpy((void*)mNCPMeshLocalAddress.s6_addr, (void*)addr->s6_addr, sizeof(mNCPMeshLocalAddress));
2446
775
    signal_property_changed(kWPANTUNDProperty_IPv6MeshLocalAddress, in6_addr_to_string(*addr));
2447
2448
    // If mesh-local prefix gets changed we go through the
2449
    // list of IPv6 addresses and filter/remove any previously
2450
    // added RLOC addresses.
2451
775
    filter_addresses();
2452
775
  }
2453
1.15k
}
2454
2455
void
2456
SpinelNCPInstance::update_mesh_local_prefix(struct in6_addr *addr)
2457
663
{
2458
663
  if (addr
2459
390
   && buffer_is_nonzero(addr->s6_addr, 8)
2460
277
   && (0 != memcmp(mNCPV6Prefix, addr, sizeof(mNCPV6Prefix)))
2461
663
  ) {
2462
149
    memcpy((void*)mNCPV6Prefix, (void*)addr, sizeof(mNCPV6Prefix));
2463
149
    struct in6_addr prefix_addr (mNCPMeshLocalAddress);
2464
    // Zero out the lower 64 bits.
2465
149
    memset(prefix_addr.s6_addr+8, 0, 8);
2466
149
    signal_property_changed(kWPANTUNDProperty_IPv6MeshLocalPrefix, in6_addr_to_string(prefix_addr) + "/64");
2467
2468
    // If mesh-local prefix gets changed we go through the
2469
    // list of IPv6 addresses and filter/remove any previously
2470
    // added RLOC addresses.
2471
149
    filter_addresses();
2472
149
  }
2473
663
}
2474
2475
// ----------------------------------------------------------------------------
2476
// Property Get Handlers
2477
2478
void
2479
SpinelNCPInstance::get_spinel_prop(CallbackWithStatusArg1 cb, spinel_prop_key_t prop_key,
2480
  const std::string &reply_format)
2481
0
{
2482
0
  start_new_task(SpinelNCPTaskSendCommand::Factory(this)
2483
0
    .set_callback(cb)
2484
0
    .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, prop_key))
2485
0
    .set_reply_format(reply_format)
2486
0
    .finish()
2487
0
  );
2488
0
}
2489
2490
void
2491
SpinelNCPInstance::get_spinel_prop_with_unpacker(CallbackWithStatusArg1 cb, spinel_prop_key_t prop_key,
2492
  ReplyUnpacker unpacker)
2493
5
{
2494
5
  start_new_task(SpinelNCPTaskSendCommand::Factory(this)
2495
5
    .set_callback(cb)
2496
5
    .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, prop_key))
2497
5
    .set_reply_unpacker(unpacker)
2498
5
    .finish()
2499
5
  );
2500
5
}
2501
2502
void SpinelNCPInstance::check_capability_prop_get(CallbackWithStatusArg1 cb, const std::string &prop_name,
2503
  unsigned int capability, PropGetHandler handler)
2504
0
{
2505
0
  if (mCapabilities.count(capability)) {
2506
0
    handler(cb, prop_name);
2507
0
  } else {
2508
0
    char error_msg[200];
2509
0
    snprintf(error_msg, sizeof(error_msg),
2510
0
      "Capability %s (required for \"%s\") is not supported by NCP", spinel_capability_to_cstr(capability),
2511
0
      prop_name.c_str());
2512
0
    cb(kWPANTUNDStatus_FeatureNotSupported, std::string(error_msg));
2513
0
  }
2514
0
}
2515
2516
void
2517
SpinelNCPInstance::register_get_handler(const char *prop_name, PropGetHandler handler)
2518
2.85M
{
2519
2.85M
  NCPInstanceBase::register_prop_get_handler(prop_name, handler);
2520
2.85M
}
2521
2522
void
2523
SpinelNCPInstance::register_get_handler_capability(const char *prop_name, unsigned int capability,
2524
  PropGetHandler handler)
2525
1.65M
{
2526
1.65M
  register_get_handler(
2527
1.65M
    prop_name,
2528
1.65M
    boost::bind(&SpinelNCPInstance::check_capability_prop_get, this, _1, _2, capability, handler));
2529
1.65M
}
2530
2531
void
2532
SpinelNCPInstance::register_get_handler_spinel_simple(const char *prop_name, spinel_prop_key_t prop_key,
2533
  const char *reply_format)
2534
487k
{
2535
487k
  register_get_handler(
2536
487k
    prop_name,
2537
487k
    boost::bind(&SpinelNCPInstance::get_spinel_prop, this, _1, prop_key, std::string(reply_format)));
2538
487k
}
2539
2540
void
2541
SpinelNCPInstance::register_get_handler_spinel_unpacker(const char *prop_name, spinel_prop_key_t prop_key,
2542
  ReplyUnpacker unpacker)
2543
153k
{
2544
153k
  register_get_handler(
2545
153k
    prop_name,
2546
153k
    boost::bind(&SpinelNCPInstance::get_spinel_prop_with_unpacker, this, _1, prop_key, unpacker));
2547
153k
}
2548
2549
void
2550
SpinelNCPInstance::register_get_handler_capability_spinel_simple(const char *prop_name, unsigned int capability,
2551
  spinel_prop_key_t prop_key, const char *reply_format)
2552
1.05M
{
2553
1.05M
  register_get_handler_capability(
2554
1.05M
    prop_name,
2555
1.05M
    capability,
2556
1.05M
    boost::bind(&SpinelNCPInstance::get_spinel_prop, this, _1, prop_key, std::string(reply_format)));
2557
1.05M
}
2558
2559
void
2560
SpinelNCPInstance::register_get_handler_capability_spinel_unpacker(const char *prop_name, unsigned int capability,
2561
  spinel_prop_key_t prop_key, ReplyUnpacker unpacker)
2562
445k
{
2563
445k
  register_get_handler_capability(
2564
445k
    prop_name,
2565
445k
    capability,
2566
445k
    boost::bind(&SpinelNCPInstance::get_spinel_prop_with_unpacker, this, _1, prop_key, unpacker));
2567
445k
}
2568
2569
void
2570
SpinelNCPInstance::regsiter_all_get_handlers(void)
2571
13.9k
{
2572
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2573
  // Properties associated with a spinel property with simple packing format
2574
2575
13.9k
  register_get_handler_spinel_simple(
2576
13.9k
    kWPANTUNDProperty_NCPCCAThreshold,
2577
13.9k
    SPINEL_PROP_PHY_CCA_THRESHOLD, SPINEL_DATATYPE_INT8_S);
2578
13.9k
  register_get_handler_spinel_simple(
2579
13.9k
    kWPANTUNDProperty_NCPTXPower,
2580
13.9k
    SPINEL_PROP_PHY_TX_POWER, SPINEL_DATATYPE_INT8_S);
2581
13.9k
  register_get_handler_spinel_simple(
2582
13.9k
    kWPANTUNDProperty_NCPFrequency,
2583
13.9k
    SPINEL_PROP_PHY_FREQ, SPINEL_DATATYPE_INT32_S);
2584
13.9k
  register_get_handler_spinel_simple(
2585
13.9k
    kWPANTUNDProperty_NetworkKey,
2586
13.9k
    SPINEL_PROP_NET_MASTER_KEY, SPINEL_DATATYPE_DATA_S);
2587
13.9k
  register_get_handler_spinel_simple(
2588
13.9k
    kWPANTUNDProperty_NetworkPSKc,
2589
13.9k
    SPINEL_PROP_NET_PSKC, SPINEL_DATATYPE_DATA_S);
2590
13.9k
  register_get_handler_spinel_simple(
2591
13.9k
    kWPANTUNDProperty_NCPExtendedAddress,
2592
13.9k
    SPINEL_PROP_MAC_EXTENDED_ADDR, SPINEL_DATATYPE_EUI64_S);
2593
13.9k
  register_get_handler_spinel_simple(
2594
13.9k
    kWPANTUNDProperty_NetworkKeyIndex,
2595
13.9k
    SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER, SPINEL_DATATYPE_UINT32_S);
2596
13.9k
  register_get_handler_spinel_simple(
2597
13.9k
    kWPANTUNDProperty_NetworkKeySwitchGuardTime,
2598
13.9k
    SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME, SPINEL_DATATYPE_UINT32_S);
2599
13.9k
  register_get_handler_spinel_simple(
2600
13.9k
    kWPANTUNDProperty_NetworkRole,
2601
13.9k
    SPINEL_PROP_NET_ROLE, SPINEL_DATATYPE_UINT8_S);
2602
13.9k
  register_get_handler_spinel_simple(
2603
13.9k
    kWPANTUNDProperty_NetworkPartitionId,
2604
13.9k
    SPINEL_PROP_NET_PARTITION_ID, SPINEL_DATATYPE_UINT32_S);
2605
13.9k
  register_get_handler_spinel_simple(
2606
13.9k
    kWPANTUNDProperty_ThreadRouterUpgradeThreshold,
2607
13.9k
    SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD, SPINEL_DATATYPE_UINT8_S);
2608
13.9k
  register_get_handler_spinel_simple(
2609
13.9k
    kWPANTUNDProperty_ThreadRouterDowngradeThreshold,
2610
13.9k
    SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD, SPINEL_DATATYPE_UINT8_S);
2611
13.9k
  register_get_handler_spinel_simple(
2612
13.9k
    kWPANTUNDProperty_NCPRSSI,
2613
13.9k
    SPINEL_PROP_PHY_RSSI, SPINEL_DATATYPE_INT8_S);
2614
13.9k
  register_get_handler_spinel_simple(
2615
13.9k
    kWPANTUNDProperty_ThreadRLOC16,
2616
13.9k
    SPINEL_PROP_THREAD_RLOC16, SPINEL_DATATYPE_UINT16_S);
2617
13.9k
  register_get_handler_spinel_simple(
2618
13.9k
    kWPANTUNDProperty_ThreadRouterSelectionJitter,
2619
13.9k
    SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER, SPINEL_DATATYPE_UINT8_S);
2620
13.9k
  register_get_handler_spinel_simple(
2621
13.9k
    kWPANTUNDProperty_ThreadLeaderAddress,
2622
13.9k
    SPINEL_PROP_THREAD_LEADER_ADDR, SPINEL_DATATYPE_IPv6ADDR_S);
2623
13.9k
  register_get_handler_spinel_simple(
2624
13.9k
    kWPANTUNDProperty_ThreadLeaderRouterID,
2625
13.9k
    SPINEL_PROP_THREAD_LEADER_RID, SPINEL_DATATYPE_UINT8_S);
2626
13.9k
  register_get_handler_spinel_simple(
2627
13.9k
    kWPANTUNDProperty_ThreadLeaderWeight,
2628
13.9k
    SPINEL_PROP_THREAD_LEADER_WEIGHT, SPINEL_DATATYPE_UINT8_S);
2629
13.9k
  register_get_handler_spinel_simple(
2630
13.9k
    kWPANTUNDProperty_ThreadLeaderLocalWeight,
2631
13.9k
    SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT, SPINEL_DATATYPE_UINT8_S);
2632
13.9k
  register_get_handler_spinel_simple(
2633
13.9k
    kWPANTUNDProperty_ThreadNetworkData,
2634
13.9k
    SPINEL_PROP_THREAD_NETWORK_DATA, SPINEL_DATATYPE_DATA_S);
2635
13.9k
  register_get_handler_spinel_simple(
2636
13.9k
    kWPANTUNDProperty_ThreadNetworkDataVersion,
2637
13.9k
    SPINEL_PROP_THREAD_NETWORK_DATA_VERSION, SPINEL_DATATYPE_UINT8_S);
2638
13.9k
  register_get_handler_spinel_simple(
2639
13.9k
    kWPANTUNDProperty_ThreadStableNetworkData,
2640
13.9k
    SPINEL_PROP_THREAD_STABLE_NETWORK_DATA, SPINEL_DATATYPE_DATA_S);
2641
13.9k
  register_get_handler_spinel_simple(
2642
13.9k
    kWPANTUNDProperty_ThreadLeaderNetworkData,
2643
13.9k
    SPINEL_PROP_THREAD_LEADER_NETWORK_DATA, SPINEL_DATATYPE_DATA_S);
2644
13.9k
  register_get_handler_spinel_simple(
2645
13.9k
    kWPANTUNDProperty_ThreadStableLeaderNetworkData,
2646
13.9k
    SPINEL_PROP_THREAD_STABLE_LEADER_NETWORK_DATA, SPINEL_DATATYPE_DATA_S);
2647
13.9k
  register_get_handler_spinel_simple(
2648
13.9k
    kWPANTUNDProperty_ThreadStableNetworkDataVersion,
2649
13.9k
    SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION, SPINEL_DATATYPE_UINT8_S);
2650
13.9k
  register_get_handler_spinel_simple(
2651
13.9k
    kWPANTUNDProperty_ThreadRouterRoleEnabled,
2652
13.9k
    SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED, SPINEL_DATATYPE_BOOL_S);
2653
13.9k
  register_get_handler_spinel_simple(
2654
13.9k
    kWPANTUNDProperty_ThreadDeviceMode,
2655
13.9k
    SPINEL_PROP_THREAD_MODE, SPINEL_DATATYPE_UINT8_S);
2656
13.9k
  register_get_handler_spinel_simple(
2657
13.9k
    kWPANTUNDProperty_OpenThreadDebugTestAssert,
2658
13.9k
    SPINEL_PROP_DEBUG_TEST_ASSERT, SPINEL_DATATYPE_BOOL_S);
2659
13.9k
  register_get_handler_spinel_simple(
2660
13.9k
    kWPANTUNDProperty_OpenThreadDebugTestWatchdog,
2661
13.9k
    SPINEL_PROP_DEBUG_TEST_WATCHDOG, SPINEL_DATATYPE_BOOL_S);
2662
13.9k
  register_get_handler_spinel_simple(
2663
13.9k
    kWPANTUNDProperty_TmfProxyEnabled,
2664
13.9k
    SPINEL_PROP_THREAD_TMF_PROXY_ENABLED, SPINEL_DATATYPE_BOOL_S);
2665
13.9k
  register_get_handler_spinel_simple(
2666
13.9k
    kWPANTUNDProperty_NCPCCAFailureRate,
2667
13.9k
    SPINEL_PROP_MAC_CCA_FAILURE_RATE, SPINEL_DATATYPE_UINT16_S);
2668
13.9k
  register_get_handler_spinel_simple(
2669
13.9k
    kWPANTUNDProperty_ThreadChildTimeout,
2670
13.9k
    SPINEL_PROP_THREAD_CHILD_TIMEOUT, SPINEL_DATATYPE_UINT32_S);
2671
13.9k
  register_get_handler_spinel_simple(
2672
13.9k
    kWPANTUNDProperty_OpenThreadLogLevel,
2673
13.9k
    SPINEL_PROP_DEBUG_NCP_LOG_LEVEL, SPINEL_DATATYPE_UINT8_S);
2674
13.9k
  register_get_handler_spinel_simple(
2675
13.9k
    kWPANTUNDProperty_OpenThreadLogTimestampBase,
2676
13.9k
    SPINEL_PROP_DEBUG_LOG_TIMESTAMP_BASE, SPINEL_DATATYPE_UINT64_S);
2677
13.9k
  register_get_handler_spinel_simple(
2678
13.9k
    kWPANTUNDProperty_OpenThreadTrelTestModeEnable,
2679
13.9k
    SPINEL_PROP_DEBUG_TREL_TEST_MODE_ENABLE, SPINEL_DATATYPE_BOOL_S);
2680
2681
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2682
  // Properties requiring capability check and associated with a spinel property
2683
  // with simple packing format
2684
2685
13.9k
  register_get_handler_capability_spinel_simple(
2686
13.9k
    kWPANTUNDProperty_NCPSleepyPollInterval,
2687
13.9k
    SPINEL_CAP_ROLE_SLEEPY,
2688
13.9k
    SPINEL_PROP_MAC_DATA_POLL_PERIOD, SPINEL_DATATYPE_UINT32_S);
2689
13.9k
  register_get_handler_capability_spinel_simple(
2690
13.9k
    kWPANTUNDProperty_CommissionerProvisioningUrl,
2691
13.9k
    SPINEL_CAP_THREAD_COMMISSIONER,
2692
13.9k
    SPINEL_PROP_MESHCOP_COMMISSIONER_PROVISIONING_URL, SPINEL_DATATYPE_UTF8_S);
2693
13.9k
  register_get_handler_capability_spinel_simple(
2694
13.9k
    kWPANTUNDProperty_CommissionerSessionId,
2695
13.9k
    SPINEL_CAP_THREAD_COMMISSIONER,
2696
13.9k
    SPINEL_PROP_MESHCOP_COMMISSIONER_SESSION_ID, SPINEL_DATATYPE_UINT16_S);
2697
13.9k
  register_get_handler_capability_spinel_simple(
2698
13.9k
    kWPANTUNDProperty_MACAllowlistEnabled,
2699
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
2700
13.9k
    SPINEL_PROP_MAC_ALLOWLIST_ENABLED, SPINEL_DATATYPE_BOOL_S);
2701
13.9k
  register_get_handler_capability_spinel_simple(
2702
13.9k
    kWPANTUNDProperty_MACDenylistEnabled,
2703
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
2704
13.9k
    SPINEL_PROP_MAC_DENYLIST_ENABLED, SPINEL_DATATYPE_BOOL_S);
2705
13.9k
  register_get_handler_capability_spinel_simple(
2706
13.9k
    kWPANTUNDProperty_JamDetectionStatus,
2707
13.9k
    SPINEL_CAP_JAM_DETECT,
2708
13.9k
    SPINEL_PROP_JAM_DETECTED, SPINEL_DATATYPE_BOOL_S);
2709
13.9k
  register_get_handler_capability_spinel_simple(
2710
13.9k
    kWPANTUNDProperty_JamDetectionEnable,
2711
13.9k
    SPINEL_CAP_JAM_DETECT,
2712
13.9k
    SPINEL_PROP_JAM_DETECT_ENABLE, SPINEL_DATATYPE_BOOL_S);
2713
13.9k
  register_get_handler_capability_spinel_simple(
2714
13.9k
    kWPANTUNDProperty_JamDetectionRssiThreshold,
2715
13.9k
    SPINEL_CAP_JAM_DETECT,
2716
13.9k
    SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD, SPINEL_DATATYPE_INT8_S);
2717
13.9k
  register_get_handler_capability_spinel_simple(
2718
13.9k
    kWPANTUNDProperty_JamDetectionWindow,
2719
13.9k
    SPINEL_CAP_JAM_DETECT,
2720
13.9k
    SPINEL_PROP_JAM_DETECT_WINDOW, SPINEL_DATATYPE_UINT8_S);
2721
13.9k
  register_get_handler_capability_spinel_simple(
2722
13.9k
    kWPANTUNDProperty_JamDetectionBusyPeriod,
2723
13.9k
    SPINEL_CAP_JAM_DETECT,
2724
13.9k
    SPINEL_PROP_JAM_DETECT_BUSY, SPINEL_DATATYPE_UINT8_S);
2725
13.9k
  register_get_handler_capability_spinel_simple(
2726
13.9k
    kWPANTUNDProperty_JamDetectionDebugHistoryBitmap,
2727
13.9k
    SPINEL_CAP_JAM_DETECT,
2728
13.9k
    SPINEL_PROP_JAM_DETECT_HISTORY_BITMAP, SPINEL_DATATYPE_UINT64_S);
2729
13.9k
  register_get_handler_capability_spinel_simple(
2730
13.9k
    kWPANTUNDProperty_ChildSupervisionInterval,
2731
13.9k
    SPINEL_CAP_CHILD_SUPERVISION,
2732
13.9k
    SPINEL_PROP_CHILD_SUPERVISION_INTERVAL, SPINEL_DATATYPE_UINT16_S);
2733
13.9k
  register_get_handler_capability_spinel_simple(
2734
13.9k
    kWPANTUNDProperty_ChildSupervisionCheckTimeout,
2735
13.9k
    SPINEL_CAP_CHILD_SUPERVISION,
2736
13.9k
    SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT, SPINEL_DATATYPE_UINT16_S);
2737
13.9k
  register_get_handler_capability_spinel_simple(
2738
13.9k
    kWPANTUNDProperty_ChannelMonitorSampleInterval,
2739
13.9k
    SPINEL_CAP_CHANNEL_MONITOR,
2740
13.9k
    SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_INTERVAL, SPINEL_DATATYPE_UINT32_S);
2741
13.9k
  register_get_handler_capability_spinel_simple(
2742
13.9k
    kWPANTUNDProperty_ChannelMonitorRssiThreshold,
2743
13.9k
    SPINEL_CAP_CHANNEL_MONITOR,
2744
13.9k
    SPINEL_PROP_CHANNEL_MONITOR_RSSI_THRESHOLD, SPINEL_DATATYPE_INT8_S);
2745
13.9k
  register_get_handler_capability_spinel_simple(
2746
13.9k
    kWPANTUNDProperty_ChannelMonitorSampleWindow,
2747
13.9k
    SPINEL_CAP_CHANNEL_MONITOR,
2748
13.9k
    SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_WINDOW, SPINEL_DATATYPE_UINT32_S);
2749
13.9k
  register_get_handler_capability_spinel_simple(
2750
13.9k
    kWPANTUNDProperty_ChannelMonitorSampleCount,
2751
13.9k
    SPINEL_CAP_CHANNEL_MONITOR,
2752
13.9k
    SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_COUNT, SPINEL_DATATYPE_UINT32_S);
2753
13.9k
  register_get_handler_capability_spinel_simple(
2754
13.9k
    kWPANTUNDProperty_ChannelManagerNewChannel,
2755
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
2756
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL, SPINEL_DATATYPE_UINT8_S);
2757
13.9k
  register_get_handler_capability_spinel_simple(
2758
13.9k
    kWPANTUNDProperty_ChannelManagerDelay,
2759
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
2760
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_DELAY, SPINEL_DATATYPE_UINT16_S);
2761
13.9k
  register_get_handler_capability_spinel_simple(
2762
13.9k
    kWPANTUNDProperty_ChannelManagerAutoSelectEnabled,
2763
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
2764
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_ENABLED, SPINEL_DATATYPE_BOOL_S);
2765
13.9k
  register_get_handler_capability_spinel_simple(
2766
13.9k
    kWPANTUNDProperty_ChannelManagerAutoSelectInterval,
2767
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
2768
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_INTERVAL, SPINEL_DATATYPE_UINT32_S);
2769
13.9k
  register_get_handler_capability_spinel_simple(
2770
13.9k
    kWPANTUNDProperty_ChannelManagerChannelSelect,
2771
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
2772
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_CHANNEL_SELECT, SPINEL_DATATYPE_BOOL_S);
2773
13.9k
  register_get_handler_capability_spinel_simple(
2774
13.9k
    kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix,
2775
13.9k
    SPINEL_CAP_NEST_LEGACY_INTERFACE,
2776
13.9k
    SPINEL_PROP_NEST_LEGACY_ULA_PREFIX, SPINEL_DATATYPE_DATA_S);
2777
13.9k
  register_get_handler_capability_spinel_simple(
2778
13.9k
    kWPANTUNDProperty_TimeSync_Period,
2779
13.9k
    SPINEL_CAP_TIME_SYNC,
2780
13.9k
    SPINEL_PROP_TIME_SYNC_PERIOD, SPINEL_DATATYPE_UINT16_S);
2781
13.9k
  register_get_handler_capability_spinel_simple(
2782
13.9k
    kWPANTUNDProperty_TimeSync_XtalThreshold,
2783
13.9k
    SPINEL_CAP_TIME_SYNC,
2784
13.9k
    SPINEL_PROP_TIME_SYNC_XTAL_THRESHOLD, SPINEL_DATATYPE_UINT16_S);
2785
13.9k
  register_get_handler_capability_spinel_simple(
2786
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_TOTAL,
2787
13.9k
    SPINEL_CAP_COUNTERS,
2788
13.9k
    SPINEL_PROP_CNTR_TX_PKT_TOTAL, SPINEL_DATATYPE_UINT32_S);
2789
13.9k
  register_get_handler_capability_spinel_simple(
2790
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_UNICAST,
2791
13.9k
    SPINEL_CAP_COUNTERS,
2792
13.9k
    SPINEL_PROP_CNTR_TX_PKT_UNICAST, SPINEL_DATATYPE_UINT32_S);
2793
13.9k
  register_get_handler_capability_spinel_simple(
2794
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_BROADCAST,
2795
13.9k
    SPINEL_CAP_COUNTERS,
2796
13.9k
    SPINEL_PROP_CNTR_TX_PKT_BROADCAST, SPINEL_DATATYPE_UINT32_S);
2797
13.9k
  register_get_handler_capability_spinel_simple(
2798
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_ACK_REQ,
2799
13.9k
    SPINEL_CAP_COUNTERS,
2800
13.9k
    SPINEL_PROP_CNTR_TX_PKT_ACK_REQ, SPINEL_DATATYPE_UINT32_S);
2801
13.9k
  register_get_handler_capability_spinel_simple(
2802
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_ACKED,
2803
13.9k
    SPINEL_CAP_COUNTERS,
2804
13.9k
    SPINEL_PROP_CNTR_TX_PKT_ACKED, SPINEL_DATATYPE_UINT32_S);
2805
13.9k
  register_get_handler_capability_spinel_simple(
2806
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_NO_ACK_REQ,
2807
13.9k
    SPINEL_CAP_COUNTERS,
2808
13.9k
    SPINEL_PROP_CNTR_TX_PKT_NO_ACK_REQ, SPINEL_DATATYPE_UINT32_S);
2809
13.9k
  register_get_handler_capability_spinel_simple(
2810
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_DATA,
2811
13.9k
    SPINEL_CAP_COUNTERS,
2812
13.9k
    SPINEL_PROP_CNTR_TX_PKT_DATA, SPINEL_DATATYPE_UINT32_S);
2813
13.9k
  register_get_handler_capability_spinel_simple(
2814
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_DATA_POLL,
2815
13.9k
    SPINEL_CAP_COUNTERS,
2816
13.9k
    SPINEL_PROP_CNTR_TX_PKT_DATA_POLL, SPINEL_DATATYPE_UINT32_S);
2817
13.9k
  register_get_handler_capability_spinel_simple(
2818
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_BEACON,
2819
13.9k
    SPINEL_CAP_COUNTERS,
2820
13.9k
    SPINEL_PROP_CNTR_TX_PKT_BEACON, SPINEL_DATATYPE_UINT32_S);
2821
13.9k
  register_get_handler_capability_spinel_simple(
2822
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_BEACON_REQ,
2823
13.9k
    SPINEL_CAP_COUNTERS,
2824
13.9k
    SPINEL_PROP_CNTR_TX_PKT_BEACON_REQ, SPINEL_DATATYPE_UINT32_S);
2825
13.9k
  register_get_handler_capability_spinel_simple(
2826
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_OTHER,
2827
13.9k
    SPINEL_CAP_COUNTERS,
2828
13.9k
    SPINEL_PROP_CNTR_TX_PKT_OTHER, SPINEL_DATATYPE_UINT32_S);
2829
13.9k
  register_get_handler_capability_spinel_simple(
2830
13.9k
    kWPANTUNDProperty_NCPCounter_TX_PKT_RETRY,
2831
13.9k
    SPINEL_CAP_COUNTERS,
2832
13.9k
    SPINEL_PROP_CNTR_TX_PKT_RETRY, SPINEL_DATATYPE_UINT32_S);
2833
13.9k
  register_get_handler_capability_spinel_simple(
2834
13.9k
    kWPANTUNDProperty_NCPCounter_TX_ERR_CCA,
2835
13.9k
    SPINEL_CAP_COUNTERS,
2836
13.9k
    SPINEL_PROP_CNTR_TX_ERR_CCA, SPINEL_DATATYPE_UINT32_S);
2837
13.9k
  register_get_handler_capability_spinel_simple(
2838
13.9k
    kWPANTUNDProperty_NCPCounter_TX_ERR_ABORT,
2839
13.9k
    SPINEL_CAP_COUNTERS,
2840
13.9k
    SPINEL_PROP_CNTR_TX_ERR_ABORT, SPINEL_DATATYPE_UINT32_S);
2841
13.9k
  register_get_handler_capability_spinel_simple(
2842
13.9k
    kWPANTUNDProperty_NCPCounter_RX_PKT_TOTAL,
2843
13.9k
    SPINEL_CAP_COUNTERS,
2844
13.9k
    SPINEL_PROP_CNTR_RX_PKT_TOTAL, SPINEL_DATATYPE_UINT32_S);
2845
13.9k
  register_get_handler_capability_spinel_simple(
2846
13.9k
    kWPANTUNDProperty_NCPCounter_RX_PKT_UNICAST,
2847
13.9k
    SPINEL_CAP_COUNTERS,
2848
13.9k
    SPINEL_PROP_CNTR_RX_PKT_UNICAST, SPINEL_DATATYPE_UINT32_S);
2849
13.9k
  register_get_handler_capability_spinel_simple(
2850
13.9k
    kWPANTUNDProperty_NCPCounter_RX_PKT_BROADCAST,
2851
13.9k
    SPINEL_CAP_COUNTERS,
2852
13.9k
    SPINEL_PROP_CNTR_RX_PKT_BROADCAST, SPINEL_DATATYPE_UINT32_S);
2853
13.9k
  register_get_handler_capability_spinel_simple(
2854
13.9k
    kWPANTUNDProperty_NCPCounter_RX_PKT_DATA,
2855
13.9k
    SPINEL_CAP_COUNTERS,
2856
13.9k
    SPINEL_PROP_CNTR_RX_PKT_DATA, SPINEL_DATATYPE_UINT32_S);
2857
13.9k
  register_get_handler_capability_spinel_simple(
2858
13.9k
    kWPANTUNDProperty_NCPCounter_RX_PKT_DATA_POLL,
2859
13.9k
    SPINEL_CAP_COUNTERS,
2860
13.9k
    SPINEL_PROP_CNTR_RX_PKT_DATA_POLL, SPINEL_DATATYPE_UINT32_S);
2861
13.9k
  register_get_handler_capability_spinel_simple(
2862
13.9k
    kWPANTUNDProperty_NCPCounter_RX_PKT_BEACON,
2863
13.9k
    SPINEL_CAP_COUNTERS,
2864
13.9k
    SPINEL_PROP_CNTR_RX_PKT_BEACON, SPINEL_DATATYPE_UINT32_S);
2865
13.9k
  register_get_handler_capability_spinel_simple(
2866
13.9k
    kWPANTUNDProperty_NCPCounter_RX_PKT_BEACON_REQ,
2867
13.9k
    SPINEL_CAP_COUNTERS,
2868
13.9k
    SPINEL_PROP_CNTR_RX_PKT_BEACON_REQ, SPINEL_DATATYPE_UINT32_S);
2869
13.9k
  register_get_handler_capability_spinel_simple(
2870
13.9k
    kWPANTUNDProperty_NCPCounter_RX_PKT_OTHER,
2871
13.9k
    SPINEL_CAP_COUNTERS,
2872
13.9k
    SPINEL_PROP_CNTR_RX_PKT_OTHER, SPINEL_DATATYPE_UINT32_S);
2873
13.9k
  register_get_handler_capability_spinel_simple(
2874
13.9k
    kWPANTUNDProperty_NCPCounter_RX_PKT_FILT_WL,
2875
13.9k
    SPINEL_CAP_COUNTERS,
2876
13.9k
    SPINEL_PROP_CNTR_RX_PKT_FILT_WL, SPINEL_DATATYPE_UINT32_S);
2877
13.9k
  register_get_handler_capability_spinel_simple(
2878
13.9k
    kWPANTUNDProperty_NCPCounter_RX_PKT_FILT_DA,
2879
13.9k
    SPINEL_CAP_COUNTERS,
2880
13.9k
    SPINEL_PROP_CNTR_RX_PKT_FILT_DA, SPINEL_DATATYPE_UINT32_S);
2881
13.9k
  register_get_handler_capability_spinel_simple(
2882
13.9k
    kWPANTUNDProperty_NCPCounter_RX_ERR_EMPTY,
2883
13.9k
    SPINEL_CAP_COUNTERS,
2884
13.9k
    SPINEL_PROP_CNTR_RX_ERR_EMPTY, SPINEL_DATATYPE_UINT32_S);
2885
13.9k
  register_get_handler_capability_spinel_simple(
2886
13.9k
    kWPANTUNDProperty_NCPCounter_RX_ERR_UKWN_NBR,
2887
13.9k
    SPINEL_CAP_COUNTERS,
2888
13.9k
    SPINEL_PROP_CNTR_RX_ERR_UKWN_NBR, SPINEL_DATATYPE_UINT32_S);
2889
13.9k
  register_get_handler_capability_spinel_simple(
2890
13.9k
    kWPANTUNDProperty_NCPCounter_RX_ERR_NVLD_SADDR,
2891
13.9k
    SPINEL_CAP_COUNTERS,
2892
13.9k
    SPINEL_PROP_CNTR_RX_ERR_NVLD_SADDR, SPINEL_DATATYPE_UINT32_S);
2893
13.9k
  register_get_handler_capability_spinel_simple(
2894
13.9k
    kWPANTUNDProperty_NCPCounter_RX_ERR_SECURITY,
2895
13.9k
    SPINEL_CAP_COUNTERS,
2896
13.9k
    SPINEL_PROP_CNTR_RX_ERR_SECURITY, SPINEL_DATATYPE_UINT32_S);
2897
13.9k
  register_get_handler_capability_spinel_simple(
2898
13.9k
    kWPANTUNDProperty_NCPCounter_RX_ERR_BAD_FCS,
2899
13.9k
    SPINEL_CAP_COUNTERS,
2900
13.9k
    SPINEL_PROP_CNTR_RX_ERR_BAD_FCS, SPINEL_DATATYPE_UINT32_S);
2901
13.9k
  register_get_handler_capability_spinel_simple(
2902
13.9k
    kWPANTUNDProperty_NCPCounter_RX_ERR_OTHER,
2903
13.9k
    SPINEL_CAP_COUNTERS,
2904
13.9k
    SPINEL_PROP_CNTR_RX_ERR_OTHER, SPINEL_DATATYPE_UINT32_S);
2905
13.9k
  register_get_handler_capability_spinel_simple(
2906
13.9k
    kWPANTUNDProperty_NCPCounter_TX_IP_SEC_TOTAL,
2907
13.9k
    SPINEL_CAP_COUNTERS,
2908
13.9k
    SPINEL_PROP_CNTR_TX_IP_SEC_TOTAL, SPINEL_DATATYPE_UINT32_S);
2909
13.9k
  register_get_handler_capability_spinel_simple(
2910
13.9k
    kWPANTUNDProperty_NCPCounter_TX_IP_INSEC_TOTAL,
2911
13.9k
    SPINEL_CAP_COUNTERS,
2912
13.9k
    SPINEL_PROP_CNTR_TX_IP_INSEC_TOTAL, SPINEL_DATATYPE_UINT32_S);
2913
13.9k
  register_get_handler_capability_spinel_simple(
2914
13.9k
    kWPANTUNDProperty_NCPCounter_TX_IP_DROPPED,
2915
13.9k
    SPINEL_CAP_COUNTERS,
2916
13.9k
    SPINEL_PROP_CNTR_TX_IP_DROPPED, SPINEL_DATATYPE_UINT32_S);
2917
13.9k
  register_get_handler_capability_spinel_simple(
2918
13.9k
    kWPANTUNDProperty_NCPCounter_RX_IP_SEC_TOTAL,
2919
13.9k
    SPINEL_CAP_COUNTERS,
2920
13.9k
    SPINEL_PROP_CNTR_RX_IP_SEC_TOTAL, SPINEL_DATATYPE_UINT32_S);
2921
13.9k
  register_get_handler_capability_spinel_simple(
2922
13.9k
    kWPANTUNDProperty_NCPCounter_RX_IP_INSEC_TOTAL,
2923
13.9k
    SPINEL_CAP_COUNTERS,
2924
13.9k
    SPINEL_PROP_CNTR_RX_IP_INSEC_TOTAL, SPINEL_DATATYPE_UINT32_S);
2925
13.9k
  register_get_handler_capability_spinel_simple(
2926
13.9k
    kWPANTUNDProperty_NCPCounter_RX_IP_DROPPED,
2927
13.9k
    SPINEL_CAP_COUNTERS,
2928
13.9k
    SPINEL_PROP_CNTR_RX_IP_DROPPED, SPINEL_DATATYPE_UINT32_S);
2929
13.9k
  register_get_handler_capability_spinel_simple(
2930
13.9k
    kWPANTUNDProperty_NCPCounter_TX_SPINEL_TOTAL,
2931
13.9k
    SPINEL_CAP_COUNTERS,
2932
13.9k
    SPINEL_PROP_CNTR_TX_SPINEL_TOTAL, SPINEL_DATATYPE_UINT32_S);
2933
13.9k
  register_get_handler_capability_spinel_simple(
2934
13.9k
    kWPANTUNDProperty_NCPCounter_RX_SPINEL_TOTAL,
2935
13.9k
    SPINEL_CAP_COUNTERS,
2936
13.9k
    SPINEL_PROP_CNTR_RX_SPINEL_TOTAL, SPINEL_DATATYPE_UINT32_S);
2937
13.9k
  register_get_handler_capability_spinel_simple(
2938
13.9k
    kWPANTUNDProperty_NCPCounter_RX_SPINEL_ERR,
2939
13.9k
    SPINEL_CAP_COUNTERS,
2940
13.9k
    SPINEL_PROP_CNTR_RX_SPINEL_ERR, SPINEL_DATATYPE_UINT32_S);
2941
13.9k
  register_get_handler_capability_spinel_simple(
2942
13.9k
    kWPANTUNDProperty_NCPCounter_IP_TX_SUCCESS,
2943
13.9k
    SPINEL_CAP_COUNTERS,
2944
13.9k
    SPINEL_PROP_CNTR_IP_TX_SUCCESS, SPINEL_DATATYPE_UINT32_S);
2945
13.9k
  register_get_handler_capability_spinel_simple(
2946
13.9k
    kWPANTUNDProperty_NCPCounter_IP_RX_SUCCESS,
2947
13.9k
    SPINEL_CAP_COUNTERS,
2948
13.9k
    SPINEL_PROP_CNTR_IP_RX_SUCCESS, SPINEL_DATATYPE_UINT32_S);
2949
13.9k
  register_get_handler_capability_spinel_simple(
2950
13.9k
    kWPANTUNDProperty_NCPCounter_IP_TX_FAILURE,
2951
13.9k
    SPINEL_CAP_COUNTERS,
2952
13.9k
    SPINEL_PROP_CNTR_IP_TX_FAILURE, SPINEL_DATATYPE_UINT32_S);
2953
13.9k
  register_get_handler_capability_spinel_simple(
2954
13.9k
    kWPANTUNDProperty_NCPCounter_IP_RX_FAILURE,
2955
13.9k
    SPINEL_CAP_COUNTERS,
2956
13.9k
    SPINEL_PROP_CNTR_IP_RX_FAILURE, SPINEL_DATATYPE_UINT32_S);
2957
13.9k
  register_get_handler_capability_spinel_simple(
2958
13.9k
    kWPANTUNDProperty_POSIXAppRCPVersion,
2959
13.9k
    SPINEL_CAP_POSIX,
2960
13.9k
    SPINEL_PROP_RCP_VERSION, SPINEL_DATATYPE_UTF8_S);
2961
13.9k
  register_get_handler_capability_spinel_simple(
2962
13.9k
    kWPANTUNDProperty_OpenThreadSLAACEnabled,
2963
13.9k
    SPINEL_CAP_SLAAC,
2964
13.9k
    SPINEL_PROP_SLAAC_ENABLED, SPINEL_DATATYPE_BOOL_S);
2965
13.9k
  register_get_handler_capability_spinel_simple(
2966
13.9k
    kWPANTUNDProperty_NCPCoexEnable,
2967
13.9k
    SPINEL_CAP_RADIO_COEX,
2968
13.9k
    SPINEL_PROP_RADIO_COEX_ENABLE, SPINEL_DATATYPE_BOOL_S);
2969
13.9k
  register_get_handler_capability_spinel_simple(
2970
13.9k
    kWPANTUNDProperty_ThreadDomainName,
2971
13.9k
    SPINEL_CAP_NET_THREAD_1_2,
2972
13.9k
    SPINEL_PROP_THREAD_DOMAIN_NAME, SPINEL_DATATYPE_UTF8_S);
2973
2974
13.9k
  register_get_handler_capability_spinel_simple(
2975
13.9k
    kWPANTUNDProperty_ThreadCslPeriod,
2976
13.9k
    SPINEL_CAP_THREAD_CSL_RECEIVER,
2977
13.9k
    SPINEL_PROP_THREAD_CSL_PERIOD, SPINEL_DATATYPE_UINT16_S);
2978
13.9k
  register_get_handler_capability_spinel_simple(
2979
13.9k
    kWPANTUNDProperty_ThreadCslTimeout,
2980
13.9k
    SPINEL_CAP_THREAD_CSL_RECEIVER,
2981
13.9k
    SPINEL_PROP_THREAD_CSL_TIMEOUT, SPINEL_DATATYPE_UINT32_S);
2982
13.9k
  register_get_handler_capability_spinel_simple(
2983
13.9k
    kWPANTUNDProperty_ThreadCslChannel,
2984
13.9k
    SPINEL_CAP_THREAD_CSL_RECEIVER,
2985
13.9k
    SPINEL_PROP_THREAD_CSL_CHANNEL, SPINEL_DATATYPE_UINT8_S);
2986
13.9k
  register_get_handler_capability_spinel_simple(
2987
13.9k
    kWPANTUNDProperty_ThreadBackboneRouterLocalJitter,
2988
13.9k
    SPINEL_CAP_THREAD_BACKBONE_ROUTER,
2989
13.9k
    SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER, SPINEL_DATATYPE_UINT8_S);
2990
2991
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2992
  // Properties associated with a spinel property using an unpacker
2993
2994
13.9k
  register_get_handler_spinel_unpacker(
2995
13.9k
    kWPANTUNDProperty_NCPChannelMask,
2996
13.9k
    SPINEL_PROP_PHY_CHAN_SUPPORTED, unpack_channel_mask);
2997
13.9k
  register_get_handler_spinel_unpacker(
2998
13.9k
    kWPANTUNDProperty_NCPPreferredChannelMask,
2999
13.9k
    SPINEL_PROP_PHY_CHAN_PREFERRED, unpack_channel_mask);
3000
13.9k
  register_get_handler_spinel_unpacker(
3001
13.9k
    kWPANTUNDProperty_ThreadActiveDataset,
3002
13.9k
    SPINEL_PROP_THREAD_ACTIVE_DATASET, boost::bind(unpack_dataset, _1, _2, _3, /* as_val_map */ false));
3003
13.9k
  register_get_handler_spinel_unpacker(
3004
13.9k
    kWPANTUNDProperty_ThreadActiveDatasetAsValMap,
3005
13.9k
    SPINEL_PROP_THREAD_ACTIVE_DATASET, boost::bind(unpack_dataset, _1, _2, _3, /* as_val_map */ true));
3006
13.9k
  register_get_handler_spinel_unpacker(
3007
13.9k
    kWPANTUNDProperty_ThreadPendingDataset,
3008
13.9k
    SPINEL_PROP_THREAD_PENDING_DATASET, boost::bind(unpack_dataset, _1, _2, _3, /* as_val_map */ false));
3009
13.9k
  register_get_handler_spinel_unpacker(
3010
13.9k
    kWPANTUNDProperty_ThreadPendingDatasetAsValMap,
3011
13.9k
    SPINEL_PROP_THREAD_PENDING_DATASET, boost::bind(unpack_dataset, _1, _2, _3, /* as_val_map */ true));
3012
13.9k
  register_get_handler_spinel_unpacker(
3013
13.9k
    kWPANTUNDProperty_ThreadParent,
3014
13.9k
    SPINEL_PROP_THREAD_PARENT,
3015
13.9k
    boost::bind(unpack_parent_info, _1, _2, _3, /* as_val_map */ false));
3016
13.9k
  register_get_handler_spinel_unpacker(
3017
13.9k
    kWPANTUNDProperty_ThreadParentAsValMap,
3018
13.9k
    SPINEL_PROP_THREAD_PARENT,
3019
13.9k
    boost::bind(unpack_parent_info, _1, _2, _3, /* as_val_map */ true));
3020
13.9k
  register_get_handler_spinel_unpacker(
3021
13.9k
    kWPANTUNDProperty_ThreadAddressCacheTable,
3022
13.9k
    SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE,
3023
13.9k
    boost::bind(unpack_address_cache_table, _1, _2, _3, /* as_val_map */ false));
3024
13.9k
  register_get_handler_spinel_unpacker(
3025
13.9k
    kWPANTUNDProperty_ThreadAddressCacheTableAsValMap,
3026
13.9k
    SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE,
3027
13.9k
    boost::bind(unpack_address_cache_table, _1, _2, _3, /* as_val_map */ true));
3028
13.9k
  register_get_handler_spinel_unpacker(
3029
13.9k
    kWPANTUNDProperty_OpenThreadSupportedRadioLinks,
3030
13.9k
    SPINEL_PROP_SUPPORTED_RADIO_LINKS,
3031
13.9k
    unpack_supported_radio_links);
3032
3033
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3034
  // Properties requiring capability check and associated with a spinel property
3035
  // using an unpacker
3036
3037
13.9k
  register_get_handler_capability_spinel_unpacker(
3038
13.9k
    kWPANTUNDProperty_NCPMCUPowerState,
3039
13.9k
    SPINEL_CAP_MCU_POWER_STATE,
3040
13.9k
    SPINEL_PROP_MCU_POWER_STATE, unpack_mcu_power_state);
3041
13.9k
  register_get_handler_capability_spinel_unpacker(
3042
13.9k
    kWPANTUNDProperty_JoinerState,
3043
13.9k
    SPINEL_CAP_THREAD_JOINER,
3044
13.9k
    SPINEL_PROP_MESHCOP_JOINER_STATE, unpack_meshcop_joiner_state);
3045
13.9k
  register_get_handler_capability_spinel_unpacker(
3046
13.9k
    kWPANTUNDProperty_JoinerDiscernerValue,
3047
13.9k
    SPINEL_CAP_THREAD_JOINER,
3048
13.9k
    SPINEL_PROP_MESHCOP_JOINER_DISCERNER, unpack_meshcop_joiner_discerner_value);
3049
13.9k
  register_get_handler_capability_spinel_unpacker(
3050
13.9k
    kWPANTUNDProperty_CommissionerState,
3051
13.9k
    SPINEL_CAP_THREAD_COMMISSIONER,
3052
13.9k
    SPINEL_PROP_MESHCOP_COMMISSIONER_STATE, unpack_commissioner_state);
3053
13.9k
  register_get_handler_capability_spinel_unpacker(
3054
13.9k
    kWPANTUNDProperty_CommissionerJoiners,
3055
13.9k
    SPINEL_CAP_THREAD_COMMISSIONER,
3056
13.9k
    SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS, unpack_commissioner_joiners);
3057
13.9k
  register_get_handler_capability_spinel_unpacker(
3058
13.9k
    kWPANTUNDProperty_MACAllowlistEntries,
3059
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
3060
13.9k
    SPINEL_PROP_MAC_ALLOWLIST, boost::bind(unpack_mac_allowlist_entries, _1, _2, _3, false));
3061
13.9k
  register_get_handler_capability_spinel_unpacker(
3062
13.9k
    kWPANTUNDProperty_MACAllowlistEntriesAsValMap,
3063
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
3064
13.9k
    SPINEL_PROP_MAC_ALLOWLIST, boost::bind(unpack_mac_allowlist_entries, _1, _2, _3, true));
3065
13.9k
  register_get_handler_capability_spinel_unpacker(
3066
13.9k
    kWPANTUNDProperty_MACDenylistEntries,
3067
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
3068
13.9k
    SPINEL_PROP_MAC_DENYLIST, boost::bind(unpack_mac_denylist_entries, _1, _2, _3, false));
3069
13.9k
  register_get_handler_capability_spinel_unpacker(
3070
13.9k
    kWPANTUNDProperty_MACDenylistEntriesAsValMap,
3071
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
3072
13.9k
    SPINEL_PROP_MAC_DENYLIST, boost::bind(unpack_mac_denylist_entries, _1, _2, _3, true));
3073
13.9k
  register_get_handler_capability_spinel_unpacker(
3074
13.9k
    kWPANTUNDProperty_MACFilterEntries,
3075
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
3076
13.9k
    SPINEL_PROP_MAC_FIXED_RSS, boost::bind(unpack_mac_allowlist_entries, _1, _2, _3, false));
3077
13.9k
  register_get_handler_capability_spinel_unpacker(
3078
13.9k
    kWPANTUNDProperty_MACFilterEntriesAsValMap,
3079
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
3080
13.9k
    SPINEL_PROP_MAC_FIXED_RSS, boost::bind(unpack_mac_allowlist_entries, _1, _2, _3, true));
3081
13.9k
  register_get_handler_capability_spinel_unpacker(
3082
13.9k
    kWPANTUNDProperty_ChannelMonitorChannelQuality,
3083
13.9k
    SPINEL_CAP_CHANNEL_MONITOR,
3084
13.9k
    SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_OCCUPANCY, boost::bind(unpack_channel_occupancy, _1, _2, _3, false));
3085
13.9k
  register_get_handler_capability_spinel_unpacker(
3086
13.9k
    kWPANTUNDProperty_ChannelMonitorChannelQualityAsValMap,
3087
13.9k
    SPINEL_CAP_CHANNEL_MONITOR,
3088
13.9k
    SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_OCCUPANCY, boost::bind(unpack_channel_occupancy, _1, _2, _3, true));
3089
13.9k
  register_get_handler_capability_spinel_unpacker(
3090
13.9k
    kWPANTUNDProperty_ChannelManagerSupportedChannelMask,
3091
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
3092
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS, unpack_channel_mask);
3093
13.9k
  register_get_handler_capability_spinel_unpacker(
3094
13.9k
    kWPANTUNDProperty_ChannelManagerFavoredChannelMask,
3095
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
3096
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_FAVORED_CHANNELS, unpack_channel_mask);
3097
13.9k
  register_get_handler_capability_spinel_unpacker(
3098
13.9k
    kWPANTUNDProperty_NCPCounterAllMac,
3099
13.9k
    SPINEL_CAP_COUNTERS,
3100
13.9k
    SPINEL_PROP_CNTR_ALL_MAC_COUNTERS, boost::bind(unpack_ncp_counters_all_mac, _1, _2, _3, false));
3101
13.9k
  register_get_handler_capability_spinel_unpacker(
3102
13.9k
    kWPANTUNDProperty_NCPCounterAllMacAsValMap,
3103
13.9k
    SPINEL_CAP_COUNTERS,
3104
13.9k
    SPINEL_PROP_CNTR_ALL_MAC_COUNTERS, boost::bind(unpack_ncp_counters_all_mac, _1, _2, _3, true));
3105
13.9k
  register_get_handler_capability_spinel_unpacker(
3106
13.9k
    kWPANTUNDProperty_NCPCounterThreadMle,
3107
13.9k
    SPINEL_CAP_COUNTERS,
3108
13.9k
    SPINEL_PROP_CNTR_MLE_COUNTERS, boost::bind(unpack_ncp_counters_mle, _1, _2, _3, false));
3109
13.9k
  register_get_handler_capability_spinel_unpacker(
3110
13.9k
    kWPANTUNDProperty_NCPCounterThreadMleAsValMap,
3111
13.9k
    SPINEL_CAP_COUNTERS,
3112
13.9k
    SPINEL_PROP_CNTR_MLE_COUNTERS, boost::bind(unpack_ncp_counters_mle, _1, _2, _3, true));
3113
13.9k
  register_get_handler_capability_spinel_unpacker(
3114
13.9k
    kWPANTUNDProperty_NCPCounterAllIPv6,
3115
13.9k
    SPINEL_CAP_COUNTERS,
3116
13.9k
    SPINEL_PROP_CNTR_ALL_IP_COUNTERS, boost::bind(unpack_ncp_counters_ipv6, _1, _2, _3, false));
3117
13.9k
  register_get_handler_capability_spinel_unpacker(
3118
13.9k
    kWPANTUNDProperty_NCPCounterAllIPv6AsValMap,
3119
13.9k
    SPINEL_CAP_COUNTERS,
3120
13.9k
    SPINEL_PROP_CNTR_ALL_IP_COUNTERS, boost::bind(unpack_ncp_counters_ipv6, _1, _2, _3, true));
3121
13.9k
  register_get_handler_capability_spinel_unpacker(
3122
13.9k
    kWPANTUNDProperty_TimeSync_NetworkTime,
3123
13.9k
    SPINEL_CAP_TIME_SYNC,
3124
13.9k
    SPINEL_PROP_THREAD_NETWORK_TIME, boost::bind(unpack_thread_network_time_as_any, _1, _2, _3, false));
3125
13.9k
  register_get_handler_capability_spinel_unpacker(
3126
13.9k
    kWPANTUNDProperty_TimeSync_NetworkTimeAsValMap,
3127
13.9k
    SPINEL_CAP_TIME_SYNC,
3128
13.9k
    SPINEL_PROP_THREAD_NETWORK_TIME, boost::bind(unpack_thread_network_time_as_any, _1, _2, _3, true));
3129
13.9k
  register_get_handler_capability_spinel_unpacker(
3130
13.9k
    kWPANTUNDProperty_ThreadLeaderServices,
3131
13.9k
    SPINEL_CAP_THREAD_SERVICE,
3132
13.9k
    SPINEL_PROP_SERVER_LEADER_SERVICES, boost::bind(unpack_server_leader_services_as_any, _1, _2, _3, false));
3133
13.9k
  register_get_handler_capability_spinel_unpacker(
3134
13.9k
    kWPANTUNDProperty_ThreadLeaderServicesAsValMap,
3135
13.9k
    SPINEL_CAP_THREAD_SERVICE,
3136
13.9k
    SPINEL_PROP_SERVER_LEADER_SERVICES, boost::bind(unpack_server_leader_services_as_any, _1, _2, _3, true));
3137
13.9k
  register_get_handler_capability_spinel_unpacker(
3138
13.9k
    kWPANTUNDProperty_NCPCoexMetrics,
3139
13.9k
    SPINEL_CAP_RADIO_COEX,
3140
13.9k
    SPINEL_PROP_RADIO_COEX_METRICS, boost::bind(unpack_coex_metrics, _1, _2, _3, false));
3141
13.9k
  register_get_handler_capability_spinel_unpacker(
3142
13.9k
    kWPANTUNDProperty_NCPCoexMetricsAsValMap,
3143
13.9k
    SPINEL_CAP_RADIO_COEX,
3144
13.9k
    SPINEL_PROP_RADIO_COEX_METRICS, boost::bind(unpack_coex_metrics, _1, _2, _3, true));
3145
13.9k
  register_get_handler_capability_spinel_unpacker(
3146
13.9k
    kWPANTUNDProperty_OpenThreadNeighborTableMultiRadioInfo,
3147
13.9k
    SPINEL_CAP_MULTI_RADIO,
3148
13.9k
    SPINEL_PROP_NEIGHBOR_TABLE_MULTI_RADIO_INFO, boost::bind(unpack_neighbor_table_multi_radio_info, _1, _2, _3));
3149
13.9k
  register_get_handler_capability_spinel_unpacker(
3150
13.9k
    kWPANTUNDProperty_ThreadDUAInterfaceIdentifier,
3151
13.9k
    SPINEL_CAP_DUA,
3152
13.9k
    SPINEL_PROP_THREAD_DUA_ID, unpack_mcu_dua_interface_identifier);
3153
13.9k
  register_get_handler_capability_spinel_unpacker(
3154
13.9k
    kWPANTUNDProperty_ThreadBackboneRouterPrimary,
3155
13.9k
    SPINEL_CAP_NET_THREAD_1_2,
3156
13.9k
    SPINEL_PROP_THREAD_BACKBONE_ROUTER_PRIMARY, boost::bind(unpack_backbone_router_primary, _1, _2, _3));
3157
13.9k
  register_get_handler_capability_spinel_unpacker(
3158
13.9k
    kWPANTUNDProperty_ThreadBackboneRouterLocalState,
3159
13.9k
    SPINEL_CAP_THREAD_BACKBONE_ROUTER,
3160
13.9k
    SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE, boost::bind(unpack_backbone_router_state, _1, _2, _3));
3161
13.9k
  register_get_handler_capability_spinel_unpacker(
3162
13.9k
    kWPANTUNDProperty_ThreadBackboneRouterLocalConfig,
3163
13.9k
    SPINEL_CAP_THREAD_BACKBONE_ROUTER,
3164
13.9k
    SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG, boost::bind(unpack_backbone_router_config, _1, _2, _3));
3165
3166
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3167
  // Properties with a dedicated handler method
3168
3169
13.9k
  register_get_handler(
3170
13.9k
    kWPANTUNDProperty_ConfigNCPDriverName,
3171
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ConfigNCPDriverName, this, _1));
3172
13.9k
  register_get_handler(
3173
13.9k
    kWPANTUNDProperty_NCPCapabilities,
3174
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_NCPCapabilities, this, _1));
3175
13.9k
  register_get_handler(
3176
13.9k
    kWPANTUNDProperty_NetworkIsCommissioned,
3177
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_NetworkIsCommissioned, this, _1));
3178
13.9k
  register_get_handler(
3179
13.9k
    kWPANTUNDProperty_ThreadRouterID,
3180
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadRouterID, this, _1));
3181
13.9k
  register_get_handler(
3182
13.9k
    kWPANTUNDProperty_ThreadConfigFilterRLOCAddresses,
3183
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadConfigFilterRLOCAddresses, this, _1));
3184
13.9k
  register_get_handler(
3185
13.9k
    kWPANTUNDProperty_ThreadConfigFilterALOCAddresses,
3186
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadConfigFilterALOCAddresses, this, _1));
3187
13.9k
  register_get_handler(
3188
13.9k
    kWPANTUNDProperty_IPv6MeshLocalPrefix,
3189
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_IPv6MeshLocalPrefix, this, _1));
3190
13.9k
  register_get_handler(
3191
13.9k
    kWPANTUNDProperty_IPv6MeshLocalAddress,
3192
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_IPv6MeshLocalAddress, this, _1));
3193
13.9k
  register_get_handler(
3194
13.9k
    kWPANTUNDProperty_IPv6LinkLocalAddress,
3195
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_IPv6LinkLocalAddress, this, _1));
3196
13.9k
  register_get_handler(
3197
13.9k
    kWPANTUNDProperty_ThreadChildTable,
3198
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadChildTable, this, _1));
3199
13.9k
  register_get_handler(
3200
13.9k
    kWPANTUNDProperty_ThreadChildTableAsValMap,
3201
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadChildTableAsValMap, this, _1));
3202
13.9k
  register_get_handler(
3203
13.9k
    kWPANTUNDProperty_ThreadChildTableAddresses,
3204
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadChildTableAddresses, this, _1));
3205
13.9k
  register_get_handler(
3206
13.9k
    kWPANTUNDProperty_ThreadNeighborTable,
3207
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadNeighborTable, this, _1));
3208
13.9k
  register_get_handler(
3209
13.9k
    kWPANTUNDProperty_ThreadNeighborTableAsValMap,
3210
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadNeighborTableAsValMap, this, _1));
3211
13.9k
  register_get_handler(
3212
13.9k
    kWPANTUNDProperty_ThreadRouterTable,
3213
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadRouterTable, this, _1));
3214
13.9k
  register_get_handler(
3215
13.9k
    kWPANTUNDProperty_ThreadRouterTableAsValMap,
3216
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadRouterTableAsValMap, this, _1));
3217
13.9k
  register_get_handler(
3218
13.9k
    kWPANTUNDProperty_OpenThreadMsgBufferCounters,
3219
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_OpenThreadMsgBufferCounters, this, _1));
3220
13.9k
  register_get_handler(
3221
13.9k
    kWPANTUNDProperty_OpenThreadMsgBufferCountersAsString,
3222
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_OpenThreadMsgBufferCountersAsString, this, _1));
3223
13.9k
  register_get_handler(
3224
13.9k
    kWPANTUNDProperty_OpenThreadSteeringDataSetWhenJoinable,
3225
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_OpenThreadSteeringDataSetWhenJoinable, this, _1));
3226
13.9k
  register_get_handler(
3227
13.9k
    kWPANTUNDProperty_OpenThreadSteeringDataAddress,
3228
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_OpenThreadSteeringDataAddress, this, _1));
3229
13.9k
  register_get_handler(
3230
13.9k
    kWPANTUNDProperty_DatasetActiveTimestamp,
3231
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetActiveTimestamp, this, _1));
3232
13.9k
  register_get_handler(
3233
13.9k
    kWPANTUNDProperty_DatasetPendingTimestamp,
3234
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetPendingTimestamp, this, _1));
3235
13.9k
  register_get_handler(
3236
13.9k
    kWPANTUNDProperty_DatasetMasterKey,
3237
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetMasterKey, this, _1));
3238
13.9k
  register_get_handler(
3239
13.9k
    kWPANTUNDProperty_DatasetNetworkName,
3240
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetNetworkName, this, _1));
3241
13.9k
  register_get_handler(
3242
13.9k
    kWPANTUNDProperty_DatasetExtendedPanId,
3243
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetExtendedPanId, this, _1));
3244
13.9k
  register_get_handler(
3245
13.9k
    kWPANTUNDProperty_DatasetMeshLocalPrefix,
3246
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetMeshLocalPrefix, this, _1));
3247
13.9k
  register_get_handler(
3248
13.9k
    kWPANTUNDProperty_DatasetDelay,
3249
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetDelay, this, _1));
3250
13.9k
  register_get_handler(
3251
13.9k
    kWPANTUNDProperty_DatasetPanId,
3252
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetPanId, this, _1));
3253
13.9k
  register_get_handler(
3254
13.9k
    kWPANTUNDProperty_DatasetChannel,
3255
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetChannel, this, _1));
3256
13.9k
  register_get_handler(
3257
13.9k
    kWPANTUNDProperty_DatasetPSKc,
3258
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetPSKc, this, _1));
3259
13.9k
  register_get_handler(
3260
13.9k
    kWPANTUNDProperty_DatasetChannelMaskPage0,
3261
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetChannelMaskPage0, this, _1));
3262
13.9k
  register_get_handler(
3263
13.9k
    kWPANTUNDProperty_DatasetSecPolicyKeyRotation,
3264
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetSecPolicyKeyRotation, this, _1));
3265
13.9k
  register_get_handler(
3266
13.9k
    kWPANTUNDProperty_DatasetSecPolicyFlags,
3267
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetSecPolicyFlags, this, _1));
3268
13.9k
  register_get_handler(
3269
13.9k
    kWPANTUNDProperty_DatasetRawTlvs,
3270
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetRawTlvs, this, _1));
3271
13.9k
  register_get_handler(
3272
13.9k
    kWPANTUNDProperty_DatasetDestIpAddress,
3273
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetDestIpAddress, this, _1));
3274
13.9k
  register_get_handler(
3275
13.9k
    kWPANTUNDProperty_DatasetAllFileds,
3276
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetAllFileds, this, _1));
3277
13.9k
  register_get_handler(
3278
13.9k
    kWPANTUNDProperty_DatasetAllFileds_AltString,
3279
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetAllFileds, this, _1));
3280
13.9k
  register_get_handler(
3281
13.9k
    kWPANTUNDProperty_DatasetAllFiledsAsValMap,
3282
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetAllFiledsAsValMap, this, _1));
3283
13.9k
  register_get_handler(
3284
13.9k
    kWPANTUNDProperty_DatasetCommand,
3285
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DatasetCommand, this, _1));
3286
13.9k
  register_get_handler(
3287
13.9k
    kWPANTUNDProperty_DaemonTickleOnHostDidWake,
3288
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_DaemonTickleOnHostDidWake, this, _1));
3289
3290
  // Properties requiring capability check with a dedicated handler method
3291
3292
13.9k
  register_get_handler_capability(
3293
13.9k
    kWPANTUNDProperty_JoinerDiscernerBitLength,
3294
13.9k
    SPINEL_CAP_THREAD_JOINER,
3295
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_JoinerDiscernerBitLength, this, _1));
3296
13.9k
  register_get_handler_capability(
3297
13.9k
    kWPANTUNDProperty_CommissionerEnergyScanResult,
3298
13.9k
    SPINEL_CAP_THREAD_COMMISSIONER,
3299
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_CommissionerEnergyScanResult, this, _1));
3300
13.9k
  register_get_handler_capability(
3301
13.9k
    kWPANTUNDProperty_CommissionerPanIdConflictResult,
3302
13.9k
    SPINEL_CAP_THREAD_COMMISSIONER,
3303
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_CommissionerPanIdConflictResult, this, _1));
3304
13.9k
  register_get_handler_capability(
3305
13.9k
    kWPANTUNDCommissionerLinkMetricsQueryResult,
3306
13.9k
    SPINEL_CAP_THREAD_LINK_METRICS,
3307
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_LinkMetricsQueryResult, this, _1));
3308
13.9k
  register_get_handler_capability(
3309
13.9k
    kWPANTUNDCommissionerLinkMetricsMgmtResponse,
3310
13.9k
    SPINEL_CAP_THREAD_LINK_METRICS,
3311
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_LinkMetricsMgmtResponse, this, _1));
3312
13.9k
  register_get_handler_capability(
3313
13.9k
    kWPANTUNDCommissionerLinkMetricsLastEnhAckIe,
3314
13.9k
    SPINEL_CAP_THREAD_LINK_METRICS,
3315
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_LinkMetricsLastEnhAckIe, this, _1));
3316
13.9k
  register_get_handler_capability(
3317
13.9k
    kWPANTUNDProperty_ThreadMlrResponse,
3318
13.9k
    SPINEL_CAP_NET_THREAD_1_2,
3319
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_MulticastListenerRegistrationResponse, this, _1));
3320
13.9k
  register_get_handler_capability(
3321
13.9k
    kWPANTUNDProperty_ThreadNeighborTableErrorRates,
3322
13.9k
    SPINEL_CAP_ERROR_RATE_TRACKING,
3323
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadNeighborTableErrorRates, this, _1));
3324
13.9k
  register_get_handler_capability(
3325
13.9k
    kWPANTUNDProperty_ThreadNeighborTableErrorRatesAsValMap,
3326
13.9k
    SPINEL_CAP_ERROR_RATE_TRACKING,
3327
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_ThreadNeighborTableErrorRatesAsValMap, this, _1));
3328
13.9k
  register_get_handler_capability(
3329
13.9k
    kWPANTUNDProperty_POSIXAppRCPVersionCached,
3330
13.9k
    SPINEL_CAP_POSIX,
3331
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_POSIXAppRCPVersionCached, this, _1));
3332
13.9k
  register_get_handler_capability(
3333
13.9k
    kWPANTUNDProperty_MACFilterFixedRssi,
3334
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
3335
13.9k
    boost::bind(&SpinelNCPInstance::get_prop_MACFilterFixedRssi, this, _1));
3336
13.9k
}
3337
3338
void
3339
SpinelNCPInstance::get_prop_ConfigNCPDriverName(CallbackWithStatusArg1 cb)
3340
0
{
3341
0
  cb(kWPANTUNDStatus_Ok, boost::any(std::string("spinel")));
3342
0
}
3343
3344
void
3345
SpinelNCPInstance::get_prop_NCPCapabilities(CallbackWithStatusArg1 cb)
3346
0
{
3347
0
  std::list<std::string> capability_list;
3348
0
  std::set<unsigned int>::iterator iter;
3349
3350
0
  for (iter = mCapabilities.begin(); iter != mCapabilities.end(); iter++) {
3351
0
    char str[200];
3352
0
    snprintf(str, sizeof(str), "%s (%d)", spinel_capability_to_cstr(*iter), *iter);
3353
0
    capability_list.push_back(std::string(str));
3354
0
  }
3355
3356
0
  cb(kWPANTUNDStatus_Ok, boost::any(capability_list));
3357
0
}
3358
3359
void
3360
SpinelNCPInstance::get_prop_NetworkIsCommissioned(CallbackWithStatusArg1 cb)
3361
0
{
3362
0
  cb(kWPANTUNDStatus_Ok, boost::any(mIsCommissioned));
3363
0
}
3364
3365
void
3366
SpinelNCPInstance::get_prop_ThreadRouterID(CallbackWithStatusArg1 cb)
3367
0
{
3368
0
  get_spinel_prop(boost::bind(convert_rloc16_to_router_id, cb, _1, _2), SPINEL_PROP_THREAD_RLOC16,
3369
0
    SPINEL_DATATYPE_UINT16_S);
3370
0
}
3371
3372
void
3373
SpinelNCPInstance::get_prop_ThreadConfigFilterRLOCAddresses(CallbackWithStatusArg1 cb)
3374
0
{
3375
0
  cb(kWPANTUNDStatus_Ok, boost::any(mFilterRLOCAddresses));
3376
0
}
3377
3378
void
3379
SpinelNCPInstance::get_prop_ThreadConfigFilterALOCAddresses(CallbackWithStatusArg1 cb)
3380
0
{
3381
0
  cb(kWPANTUNDStatus_Ok, boost::any(mFilterALOCAddresses));
3382
0
}
3383
3384
void
3385
SpinelNCPInstance::get_prop_JoinerDiscernerBitLength(CallbackWithStatusArg1 cb)
3386
0
{
3387
0
  cb(kWPANTUNDStatus_Ok, boost::any(mJoinerDiscernerBitLength));
3388
0
}
3389
3390
void
3391
SpinelNCPInstance::get_prop_CommissionerEnergyScanResult(CallbackWithStatusArg1 cb)
3392
0
{
3393
0
  cb(kWPANTUNDStatus_Ok, boost::any(mCommissionerEnergyScanResult));
3394
0
}
3395
3396
void
3397
SpinelNCPInstance::get_prop_CommissionerPanIdConflictResult(CallbackWithStatusArg1 cb)
3398
0
{
3399
0
  cb(kWPANTUNDStatus_Ok, boost::any(mCommissionerPanIdConflictResult));
3400
0
}
3401
3402
void
3403
SpinelNCPInstance::get_prop_IPv6MeshLocalPrefix(CallbackWithStatusArg1 cb)
3404
0
{
3405
0
  if (!buffer_is_nonzero(mNCPV6Prefix, sizeof(mNCPV6Prefix))) {
3406
0
    get_spinel_prop_with_unpacker(cb, SPINEL_PROP_IPV6_ML_PREFIX, unpack_mesh_local_prefix);
3407
0
  } else {
3408
0
    struct in6_addr addr = mNCPMeshLocalAddress;
3409
0
    memset(addr.s6_addr + 8, 0, 8);
3410
0
    cb(kWPANTUNDStatus_Ok, boost::any(in6_addr_to_string(addr) + "/64"));
3411
0
  }
3412
0
}
3413
3414
void
3415
SpinelNCPInstance::get_prop_IPv6MeshLocalAddress(CallbackWithStatusArg1 cb)
3416
0
{
3417
0
  if (!buffer_is_nonzero(mNCPV6Prefix, sizeof(mNCPV6Prefix))) {
3418
0
    get_spinel_prop(cb, SPINEL_PROP_IPV6_ML_ADDR, SPINEL_DATATYPE_IPv6ADDR_S);
3419
0
  } else {
3420
0
    cb(kWPANTUNDStatus_Ok, boost::any(in6_addr_to_string(mNCPMeshLocalAddress)));
3421
0
  }
3422
0
}
3423
3424
void
3425
SpinelNCPInstance::get_prop_IPv6LinkLocalAddress(CallbackWithStatusArg1 cb)
3426
0
{
3427
0
  if (!IN6_IS_ADDR_LINKLOCAL(&mNCPLinkLocalAddress)) {
3428
0
    get_spinel_prop(cb, SPINEL_PROP_IPV6_LL_ADDR, SPINEL_DATATYPE_IPv6ADDR_S);
3429
0
  } else {
3430
0
    cb(kWPANTUNDStatus_Ok, boost::any(in6_addr_to_string(mNCPLinkLocalAddress)));
3431
0
  }
3432
0
}
3433
3434
void
3435
SpinelNCPInstance::get_prop_LinkMetricsQueryResult(CallbackWithStatusArg1 cb)
3436
0
{
3437
0
  cb(kWPANTUNDStatus_Ok, boost::any(mLinkMetricsQueryResult));
3438
0
}
3439
3440
void
3441
SpinelNCPInstance::get_prop_LinkMetricsMgmtResponse(CallbackWithStatusArg1 cb)
3442
0
{
3443
0
  cb(kWPANTUNDStatus_Ok, boost::any(mLinkMetricsMgmtResponse));
3444
0
}
3445
3446
void
3447
SpinelNCPInstance::get_prop_LinkMetricsLastEnhAckIe(CallbackWithStatusArg1 cb)
3448
0
{
3449
0
  cb(kWPANTUNDStatus_Ok, boost::any(mLinkMetricsLastEnhAckIe));
3450
0
}
3451
3452
void
3453
SpinelNCPInstance::get_prop_MulticastListenerRegistrationResponse(CallbackWithStatusArg1 cb)
3454
0
{
3455
0
  cb(kWPANTUNDStatus_Ok, boost::any(mMulticastListenerRegistrationResponse));
3456
0
}
3457
3458
void
3459
SpinelNCPInstance::get_prop_ThreadChildTable(CallbackWithStatusArg1 cb)
3460
0
{
3461
0
  start_new_task(boost::shared_ptr<SpinelNCPTask>(
3462
0
    new SpinelNCPTaskGetNetworkTopology(
3463
0
      this,
3464
0
      cb,
3465
0
      SpinelNCPTaskGetNetworkTopology::kChildTable,
3466
0
      SpinelNCPTaskGetNetworkTopology::kResultFormat_StringArray
3467
0
    )
3468
0
  ));
3469
0
}
3470
3471
void
3472
SpinelNCPInstance::get_prop_ThreadChildTableAsValMap(CallbackWithStatusArg1 cb)
3473
0
{
3474
0
  start_new_task(boost::shared_ptr<SpinelNCPTask>(
3475
0
    new SpinelNCPTaskGetNetworkTopology(
3476
0
      this,
3477
0
      cb,
3478
0
      SpinelNCPTaskGetNetworkTopology::kChildTable,
3479
0
      SpinelNCPTaskGetNetworkTopology::kResultFormat_ValueMapArray
3480
0
    )
3481
0
  ));
3482
0
}
3483
3484
void
3485
SpinelNCPInstance::get_prop_ThreadChildTableAddresses(CallbackWithStatusArg1 cb)
3486
0
{
3487
0
  start_new_task(boost::shared_ptr<SpinelNCPTask>(
3488
0
    new SpinelNCPTaskGetNetworkTopology(
3489
0
      this,
3490
0
      cb,
3491
0
      SpinelNCPTaskGetNetworkTopology::kChildTableAddresses,
3492
0
      SpinelNCPTaskGetNetworkTopology::kResultFormat_StringArray
3493
0
    )
3494
0
  ));
3495
0
}
3496
3497
void
3498
SpinelNCPInstance::get_prop_ThreadNeighborTable(CallbackWithStatusArg1 cb)
3499
0
{
3500
0
  start_new_task(boost::shared_ptr<SpinelNCPTask>(
3501
0
    new SpinelNCPTaskGetNetworkTopology(
3502
0
      this,
3503
0
      cb,
3504
0
      SpinelNCPTaskGetNetworkTopology::kNeighborTable,
3505
0
      SpinelNCPTaskGetNetworkTopology::kResultFormat_StringArray
3506
0
    )
3507
0
  ));
3508
0
}
3509
3510
void
3511
SpinelNCPInstance::get_prop_ThreadNeighborTableAsValMap(CallbackWithStatusArg1 cb)
3512
0
{
3513
0
  start_new_task(boost::shared_ptr<SpinelNCPTask>(
3514
0
    new SpinelNCPTaskGetNetworkTopology(
3515
0
      this,
3516
0
      cb,
3517
0
      SpinelNCPTaskGetNetworkTopology::kNeighborTable,
3518
0
      SpinelNCPTaskGetNetworkTopology::kResultFormat_ValueMapArray
3519
0
    )
3520
0
  ));
3521
0
}
3522
3523
void
3524
SpinelNCPInstance::get_prop_ThreadNeighborTableErrorRates(CallbackWithStatusArg1 cb)
3525
0
{
3526
0
  start_new_task(boost::shared_ptr<SpinelNCPTask>(
3527
0
    new SpinelNCPTaskGetNetworkTopology(
3528
0
      this,
3529
0
      cb,
3530
0
      SpinelNCPTaskGetNetworkTopology::kNeighborTableErrorRates,
3531
0
        SpinelNCPTaskGetNetworkTopology::kResultFormat_StringArray
3532
0
    )
3533
0
  ));
3534
0
}
3535
3536
void
3537
SpinelNCPInstance::get_prop_ThreadNeighborTableErrorRatesAsValMap(CallbackWithStatusArg1 cb)
3538
0
{
3539
0
  start_new_task(boost::shared_ptr<SpinelNCPTask>(
3540
0
    new SpinelNCPTaskGetNetworkTopology(
3541
0
      this,
3542
0
      cb,
3543
0
      SpinelNCPTaskGetNetworkTopology::kNeighborTableErrorRates,
3544
0
        SpinelNCPTaskGetNetworkTopology::kResultFormat_ValueMapArray
3545
0
    )
3546
0
  ));
3547
0
}
3548
3549
void
3550
SpinelNCPInstance::get_prop_ThreadRouterTable(CallbackWithStatusArg1 cb)
3551
0
{
3552
0
  start_new_task(boost::shared_ptr<SpinelNCPTask>(
3553
0
    new SpinelNCPTaskGetNetworkTopology(
3554
0
      this,
3555
0
      cb,
3556
0
      SpinelNCPTaskGetNetworkTopology::kRouterTable,
3557
0
      SpinelNCPTaskGetNetworkTopology::kResultFormat_StringArray
3558
0
    )
3559
0
  ));
3560
0
}
3561
3562
void
3563
SpinelNCPInstance::get_prop_ThreadRouterTableAsValMap(CallbackWithStatusArg1 cb)
3564
0
{
3565
0
  start_new_task(boost::shared_ptr<SpinelNCPTask>(
3566
0
    new SpinelNCPTaskGetNetworkTopology(
3567
0
      this,
3568
0
      cb,
3569
0
      SpinelNCPTaskGetNetworkTopology::kRouterTable,
3570
0
      SpinelNCPTaskGetNetworkTopology::kResultFormat_ValueMapArray
3571
0
    )
3572
0
  ));
3573
0
}
3574
3575
void
3576
SpinelNCPInstance::get_prop_OpenThreadMsgBufferCounters(CallbackWithStatusArg1 cb)
3577
0
{
3578
0
  start_new_task(boost::shared_ptr<SpinelNCPTask>(
3579
0
    new SpinelNCPTaskGetMsgBufferCounters(
3580
0
      this,
3581
0
      cb,
3582
0
      SpinelNCPTaskGetMsgBufferCounters::kResultFormat_StringArray
3583
0
    )
3584
0
  ));
3585
0
}
3586
3587
void
3588
SpinelNCPInstance::get_prop_OpenThreadMsgBufferCountersAsString(CallbackWithStatusArg1 cb)
3589
0
{
3590
0
  start_new_task(boost::shared_ptr<SpinelNCPTask>(
3591
0
    new SpinelNCPTaskGetMsgBufferCounters(
3592
0
      this,
3593
0
      cb,
3594
0
      SpinelNCPTaskGetMsgBufferCounters::kResultFormat_String
3595
0
    )
3596
0
  ));
3597
0
}
3598
3599
void
3600
SpinelNCPInstance::get_prop_OpenThreadSteeringDataSetWhenJoinable(CallbackWithStatusArg1 cb)
3601
0
{
3602
0
  cb(0, boost::any(mSetSteeringDataWhenJoinable));
3603
0
}
3604
3605
void
3606
SpinelNCPInstance::get_prop_OpenThreadSteeringDataAddress(CallbackWithStatusArg1 cb)
3607
0
{
3608
0
  cb(0, boost::any(nl::Data(mSteeringDataAddress, sizeof(mSteeringDataAddress))));
3609
0
}
3610
3611
void
3612
SpinelNCPInstance::get_prop_DatasetActiveTimestamp(CallbackWithStatusArg1 cb)
3613
0
{
3614
0
  if (mLocalDataset.mActiveTimestamp.has_value()) {
3615
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mActiveTimestamp.get()));
3616
0
  } else {
3617
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3618
0
  }
3619
0
}
3620
3621
void
3622
SpinelNCPInstance::get_prop_DatasetPendingTimestamp(CallbackWithStatusArg1 cb)
3623
0
{
3624
0
  if (mLocalDataset.mPendingTimestamp.has_value()) {
3625
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mPendingTimestamp.get()));
3626
0
  } else {
3627
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3628
0
  }
3629
0
}
3630
3631
void
3632
SpinelNCPInstance::get_prop_DatasetMasterKey(CallbackWithStatusArg1 cb)
3633
0
{
3634
0
  if (mLocalDataset.mMasterKey.has_value()) {
3635
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mMasterKey.get()));
3636
0
  } else {
3637
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3638
0
  }
3639
0
}
3640
3641
void
3642
SpinelNCPInstance::get_prop_DatasetNetworkName(CallbackWithStatusArg1 cb)
3643
0
{
3644
0
  if (mLocalDataset.mNetworkName.has_value()) {
3645
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mNetworkName.get()));
3646
0
  } else {
3647
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3648
0
  }
3649
0
}
3650
3651
void
3652
SpinelNCPInstance::get_prop_DatasetExtendedPanId(CallbackWithStatusArg1 cb)
3653
0
{
3654
0
  if (mLocalDataset.mExtendedPanId.has_value()) {
3655
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mExtendedPanId.get()));
3656
0
  } else {
3657
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3658
0
  }
3659
0
}
3660
3661
void
3662
SpinelNCPInstance::get_prop_DatasetMeshLocalPrefix(CallbackWithStatusArg1 cb)
3663
0
{
3664
0
  if (mLocalDataset.mMeshLocalPrefix.has_value()) {
3665
0
    cb(kWPANTUNDStatus_Ok, boost::any(in6_addr_to_string(mLocalDataset.mMeshLocalPrefix.get())));
3666
0
  } else {
3667
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3668
0
  }
3669
0
}
3670
3671
void
3672
SpinelNCPInstance::get_prop_DatasetDelay(CallbackWithStatusArg1 cb)
3673
0
{
3674
0
  if (mLocalDataset.mDelay.has_value()) {
3675
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mDelay.get()));
3676
0
  } else {
3677
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3678
0
  }
3679
0
}
3680
3681
void
3682
SpinelNCPInstance::get_prop_DatasetPanId(CallbackWithStatusArg1 cb)
3683
0
{
3684
0
  if (mLocalDataset.mPanId.has_value()) {
3685
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mPanId.get()));
3686
0
  } else {
3687
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3688
0
  }
3689
0
}
3690
3691
void
3692
SpinelNCPInstance::get_prop_DatasetChannel(CallbackWithStatusArg1 cb)
3693
0
{
3694
0
  if (mLocalDataset.mChannel.has_value()) {
3695
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mChannel.get()));
3696
0
  } else {
3697
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3698
0
  }
3699
0
}
3700
3701
void
3702
SpinelNCPInstance::get_prop_DatasetPSKc(CallbackWithStatusArg1 cb)
3703
0
{
3704
0
  if (mLocalDataset.mPSKc.has_value()) {
3705
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mPSKc.get()));
3706
0
  } else {
3707
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3708
0
  }
3709
0
}
3710
3711
void
3712
SpinelNCPInstance::get_prop_DatasetChannelMaskPage0(CallbackWithStatusArg1 cb)
3713
0
{
3714
0
  if (mLocalDataset.mChannelMaskPage0.has_value()) {
3715
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mChannelMaskPage0.get()));
3716
0
  } else {
3717
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3718
0
  }
3719
0
}
3720
3721
void
3722
SpinelNCPInstance::get_prop_DatasetSecPolicyKeyRotation(CallbackWithStatusArg1 cb)
3723
0
{
3724
0
  if (mLocalDataset.mSecurityPolicy.has_value()) {
3725
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mSecurityPolicy.get().mKeyRotationTime));
3726
0
  } else {
3727
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3728
0
  }
3729
0
}
3730
3731
void
3732
SpinelNCPInstance::get_prop_DatasetSecPolicyFlags(CallbackWithStatusArg1 cb)
3733
0
{
3734
0
  if (mLocalDataset.mSecurityPolicy.has_value()) {
3735
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mSecurityPolicy.get().mFlags));
3736
0
  } else {
3737
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3738
0
  }
3739
0
}
3740
3741
void
3742
SpinelNCPInstance::get_prop_DatasetRawTlvs(CallbackWithStatusArg1 cb)
3743
0
{
3744
0
  if (mLocalDataset.mRawTlvs.has_value()) {
3745
0
    cb(kWPANTUNDStatus_Ok, boost::any(mLocalDataset.mRawTlvs.get()));
3746
0
  } else {
3747
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3748
0
  }
3749
0
}
3750
3751
void
3752
SpinelNCPInstance::get_prop_DatasetDestIpAddress(CallbackWithStatusArg1 cb)
3753
0
{
3754
0
  if (mLocalDataset.mDestIpAddress.has_value()) {
3755
0
    cb(kWPANTUNDStatus_Ok, boost::any(in6_addr_to_string(mLocalDataset.mDestIpAddress.get())));
3756
0
  } else {
3757
0
    cb(kWPANTUNDStatus_Ok, boost::any(Data()));
3758
0
  }
3759
0
}
3760
3761
void
3762
SpinelNCPInstance::get_prop_DatasetAllFileds(CallbackWithStatusArg1 cb)
3763
0
{
3764
0
  std::list<std::string> list;
3765
0
  mLocalDataset.convert_to_string_list(list);
3766
0
  cb(kWPANTUNDStatus_Ok, boost::any(list));
3767
0
}
3768
3769
void
3770
SpinelNCPInstance::get_prop_DatasetAllFiledsAsValMap(CallbackWithStatusArg1 cb)
3771
0
{
3772
0
  ValueMap map;
3773
0
  mLocalDataset.convert_to_valuemap(map);
3774
0
  cb(kWPANTUNDStatus_Ok, boost::any(map));
3775
0
}
3776
3777
void
3778
SpinelNCPInstance::get_prop_DatasetCommand(CallbackWithStatusArg1 cb)
3779
0
{
3780
0
  std::list<std::string> help_string;
3781
0
  get_dataset_command_help(help_string);
3782
0
  cb(kWPANTUNDStatus_Ok, boost::any(help_string));
3783
0
}
3784
3785
void
3786
SpinelNCPInstance::get_prop_DaemonTickleOnHostDidWake(CallbackWithStatusArg1 cb)
3787
0
{
3788
0
  cb(kWPANTUNDStatus_Ok, boost::any(mTickleOnHostDidWake));
3789
0
}
3790
3791
void
3792
SpinelNCPInstance::get_prop_POSIXAppRCPVersionCached(CallbackWithStatusArg1 cb)
3793
0
{
3794
0
  cb(kWPANTUNDStatus_Ok, boost::any(mRcpVersion));
3795
0
}
3796
3797
void
3798
SpinelNCPInstance::get_prop_MACFilterFixedRssi(CallbackWithStatusArg1 cb)
3799
0
{
3800
0
  cb(kWPANTUNDStatus_Ok, boost::any(mMacFilterFixedRssi));
3801
0
}
3802
3803
void
3804
SpinelNCPInstance::property_get_value(
3805
  const std::string& key,
3806
  CallbackWithStatusArg1 cb
3807
2.57M
) {
3808
2.57M
  if (!is_initializing_ncp()) {
3809
796
    syslog(LOG_INFO, "property_get_value: key: \"%s\"", key.c_str());
3810
796
  }
3811
3812
2.57M
  if (mVendorCustom.is_property_key_supported(key)) {
3813
0
    mVendorCustom.property_get_value(key, cb);
3814
2.57M
  } else {
3815
2.57M
    NCPInstanceBase::property_get_value(key, cb);
3816
2.57M
  }
3817
2.57M
}
3818
3819
// ----------------------------------------------------------------------------
3820
// Property Set Handlers
3821
3822
void
3823
SpinelNCPInstance::set_spinel_prop(
3824
  const boost::any &value, CallbackWithStatus cb, spinel_prop_key_t prop_key, char pack_type, unsigned int capability,
3825
  bool save_in_settings, const std::string &prop_name)
3826
1.68k
{
3827
1.68k
  Data command = SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_NULL_S), prop_key);
3828
1.68k
  int status = SpinelAppendAny(command, value, pack_type);
3829
3830
1.68k
  if (status != kWPANTUNDStatus_Ok) {
3831
16
    cb(status);
3832
1.66k
  } else {
3833
3834
1.66k
    if (save_in_settings) {
3835
614
      mSettings[prop_name] = SettingsEntry(command, capability);
3836
614
    }
3837
3838
1.66k
    if (!capability || mCapabilities.count(capability)) {
3839
1.12k
      start_new_task(SpinelNCPTaskSendCommand::Factory(this)
3840
1.12k
        .set_callback(cb)
3841
1.12k
        .add_command(command)
3842
1.12k
        .finish()
3843
1.12k
      );
3844
1.12k
    } else {
3845
543
      cb(kWPANTUNDStatus_FeatureNotSupported);
3846
543
    }
3847
1.66k
  }
3848
1.68k
}
3849
3850
void
3851
SpinelNCPInstance::convert_value_prop_set(const boost::any &value, CallbackWithStatus cb, const std::string &prop_name,
3852
  ValueConverter converter, PropUpdateHandler handler)
3853
1.18k
{
3854
1.18k
  boost::any converted_value;
3855
1.18k
  int status = converter(value, converted_value);
3856
3857
1.18k
  if (status == kWPANTUNDStatus_Ok) {
3858
454
    handler(converted_value, cb, prop_name);
3859
734
  } else {
3860
734
    cb(status);
3861
734
  }
3862
1.18k
}
3863
3864
void
3865
SpinelNCPInstance::register_set_handler(const char *prop_name, PropUpdateHandler handler, ValueConverter converter)
3866
1.28M
{
3867
1.28M
  if (converter.empty()) {
3868
1.11M
    NCPInstanceBase::register_prop_set_handler(prop_name, handler);
3869
1.11M
  } else {
3870
3871
    // If a `converter` function is given, use `convert_value_prop_set`
3872
    // which converts the value using the `converter` then passing the
3873
    // converted value to the original `handler`.
3874
167k
    NCPInstanceBase::register_prop_set_handler(
3875
167k
      prop_name,
3876
167k
      boost::bind(&SpinelNCPInstance::convert_value_prop_set, _1, _2, _3, converter, handler));
3877
167k
  }
3878
1.28M
}
3879
3880
void
3881
SpinelNCPInstance::register_set_handler_spinel(const char *prop_name, spinel_prop_key_t prop_key, char pack_type,
3882
  ValueConverter converter)
3883
222k
{
3884
222k
  register_set_handler(
3885
222k
    prop_name,
3886
222k
    boost::bind(&SpinelNCPInstance::set_spinel_prop, this, _1, _2, prop_key, pack_type, 0, false, _3),
3887
222k
    converter);
3888
222k
}
3889
3890
void
3891
SpinelNCPInstance::register_set_handler_spinel_persist(const char *prop_name, spinel_prop_key_t prop_key,
3892
  char pack_type, ValueConverter converter)
3893
83.6k
{
3894
83.6k
  register_set_handler(
3895
83.6k
    prop_name,
3896
83.6k
    boost::bind(&SpinelNCPInstance::set_spinel_prop, this, _1, _2, prop_key, pack_type, 0, true, _3),
3897
83.6k
    converter);
3898
83.6k
}
3899
3900
void
3901
SpinelNCPInstance::register_set_handler_capability_spinel(const char *prop_name, unsigned int capability,
3902
  spinel_prop_key_t prop_key, char pack_type, ValueConverter converter)
3903
306k
{
3904
306k
  register_set_handler(
3905
306k
    prop_name,
3906
306k
    boost::bind(&SpinelNCPInstance::set_spinel_prop, this, _1, _2, prop_key, pack_type, capability, false, _3),
3907
306k
    converter);
3908
306k
}
3909
3910
void
3911
SpinelNCPInstance::register_set_handler_capability_spinel_persist(const char *prop_name, unsigned int capability,
3912
  spinel_prop_key_t prop_key, char pack_type, ValueConverter converter)
3913
250k
{
3914
250k
  register_set_handler(
3915
250k
    prop_name,
3916
250k
    boost::bind(&SpinelNCPInstance::set_spinel_prop, this, _1, _2, prop_key, pack_type, capability, true, _3),
3917
250k
    converter);
3918
250k
}
3919
3920
void
3921
SpinelNCPInstance::regsiter_all_set_handlers(void)
3922
13.9k
{
3923
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3924
  // Properties associated with a spinel property
3925
3926
13.9k
  register_set_handler_spinel(
3927
13.9k
    kWPANTUNDProperty_NCPChannel,
3928
13.9k
    SPINEL_PROP_PHY_CHAN, SPINEL_DATATYPE_UINT8_C);
3929
13.9k
  register_set_handler_spinel(
3930
13.9k
    kWPANTUNDProperty_NetworkPANID,
3931
13.9k
    SPINEL_PROP_MAC_15_4_PANID, SPINEL_DATATYPE_UINT16_C);
3932
13.9k
  register_set_handler_spinel(
3933
13.9k
    kWPANTUNDProperty_NetworkPSKc,
3934
13.9k
    SPINEL_PROP_NET_PSKC, SPINEL_DATATYPE_DATA_C);
3935
13.9k
  register_set_handler_spinel(
3936
13.9k
    kWPANTUNDProperty_NetworkPartitionId,
3937
13.9k
    SPINEL_PROP_NET_PARTITION_ID, SPINEL_DATATYPE_UINT32_C);
3938
13.9k
  register_set_handler_spinel(
3939
13.9k
    kWPANTUNDProperty_NCPMACAddress,
3940
13.9k
    SPINEL_PROP_MAC_15_4_LADDR, SPINEL_DATATYPE_EUI64_C);
3941
13.9k
  register_set_handler_spinel(
3942
13.9k
    kWPANTUNDProperty_NCPExtendedAddress,
3943
13.9k
    SPINEL_PROP_MAC_EXTENDED_ADDR, SPINEL_DATATYPE_EUI64_C);
3944
13.9k
  register_set_handler_spinel(
3945
13.9k
    kWPANTUNDProperty_NetworkKeyIndex,
3946
13.9k
    SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER, SPINEL_DATATYPE_UINT32_C);
3947
13.9k
  register_set_handler_spinel(
3948
13.9k
    kWPANTUNDProperty_NetworkKeySwitchGuardTime,
3949
13.9k
    SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME, SPINEL_DATATYPE_UINT32_C);
3950
13.9k
  register_set_handler_spinel(
3951
13.9k
    kWPANTUNDProperty_NetworkName,
3952
13.9k
    SPINEL_PROP_NET_NETWORK_NAME, SPINEL_DATATYPE_UTF8_C);
3953
13.9k
  register_set_handler_spinel(
3954
13.9k
    kWPANTUNDProperty_NetworkRole,
3955
13.9k
    SPINEL_PROP_NET_ROLE, SPINEL_DATATYPE_UINT8_C);
3956
13.9k
  register_set_handler_spinel(
3957
13.9k
    kWPANTUNDProperty_ThreadPreferredRouterID,
3958
13.9k
    SPINEL_PROP_THREAD_PREFERRED_ROUTER_ID, SPINEL_DATATYPE_UINT8_C);
3959
13.9k
  register_set_handler_spinel(
3960
13.9k
    kWPANTUNDProperty_ThreadRouterRoleEnabled,
3961
13.9k
    SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED, SPINEL_DATATYPE_BOOL_C);
3962
13.9k
  register_set_handler_spinel(
3963
13.9k
    kWPANTUNDProperty_ThreadRouterSelectionJitter,
3964
13.9k
    SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER, SPINEL_DATATYPE_UINT8_C);
3965
13.9k
  register_set_handler_spinel(
3966
13.9k
    kWPANTUNDProperty_ThreadRouterUpgradeThreshold,
3967
13.9k
    SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD, SPINEL_DATATYPE_UINT8_C);
3968
13.9k
  register_set_handler_spinel(
3969
13.9k
    kWPANTUNDProperty_ThreadRouterDowngradeThreshold,
3970
13.9k
    SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD, SPINEL_DATATYPE_UINT8_C);
3971
13.9k
  register_set_handler_spinel(
3972
13.9k
    kWPANTUNDProperty_OpenThreadTrelTestModeEnable,
3973
13.9k
    SPINEL_PROP_DEBUG_TREL_TEST_MODE_ENABLE, SPINEL_DATATYPE_BOOL_C);
3974
3975
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3976
  // Properties requiring persistence (saving in settings) and associated with a
3977
  // spinel property
3978
3979
13.9k
  register_set_handler_spinel_persist(
3980
13.9k
    kWPANTUNDProperty_NCPCCAThreshold,
3981
13.9k
    SPINEL_PROP_PHY_CCA_THRESHOLD, SPINEL_DATATYPE_INT8_C);
3982
13.9k
  register_set_handler_spinel_persist(
3983
13.9k
    kWPANTUNDProperty_NCPTXPower,
3984
13.9k
    SPINEL_PROP_PHY_TX_POWER, SPINEL_DATATYPE_INT8_C);
3985
13.9k
  register_set_handler_spinel_persist(
3986
13.9k
    kWPANTUNDProperty_ThreadChildTimeout,
3987
13.9k
    SPINEL_PROP_THREAD_CHILD_TIMEOUT, SPINEL_DATATYPE_UINT32_C);
3988
13.9k
  register_set_handler_spinel_persist(
3989
13.9k
    kWPANTUNDProperty_ThreadDeviceMode,
3990
13.9k
    SPINEL_PROP_THREAD_MODE, SPINEL_DATATYPE_UINT8_C);
3991
13.9k
  register_set_handler_spinel_persist(
3992
13.9k
    kWPANTUNDProperty_OpenThreadLogLevel,
3993
13.9k
    SPINEL_PROP_DEBUG_NCP_LOG_LEVEL, SPINEL_DATATYPE_UINT8_C);
3994
3995
  // Properties with a `ValueConverter`
3996
13.9k
  register_set_handler_spinel_persist(
3997
13.9k
    kWPANTUNDProperty_NCPChannelMask,
3998
13.9k
    SPINEL_PROP_PHY_CHAN_SUPPORTED, SPINEL_DATATYPE_DATA_C,
3999
13.9k
    &SpinelNCPInstance::convert_value_channel_mask);
4000
4001
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4002
  // Properties requiring capability check and associated with a spinel property
4003
4004
13.9k
  register_set_handler_capability_spinel(
4005
13.9k
    kWPANTUNDProperty_MACAllowlistEnabled,
4006
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
4007
13.9k
    SPINEL_PROP_MAC_ALLOWLIST_ENABLED, SPINEL_DATATYPE_BOOL_C);
4008
13.9k
  register_set_handler_capability_spinel(
4009
13.9k
    kWPANTUNDProperty_MACDenylistEnabled,
4010
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
4011
13.9k
    SPINEL_PROP_MAC_DENYLIST_ENABLED, SPINEL_DATATYPE_BOOL_C);
4012
13.9k
  register_set_handler_capability_spinel(
4013
13.9k
    kWPANTUNDProperty_CommissionerProvisioningUrl,
4014
13.9k
    SPINEL_CAP_THREAD_COMMISSIONER,
4015
13.9k
    SPINEL_PROP_MESHCOP_COMMISSIONER_PROVISIONING_URL, SPINEL_DATATYPE_UTF8_C);
4016
13.9k
  register_set_handler_capability_spinel(
4017
13.9k
    kWPANTUNDProperty_CommissionerSendMgmtGet,
4018
13.9k
    SPINEL_CAP_THREAD_COMMISSIONER,
4019
13.9k
    SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_GET, SPINEL_DATATYPE_DATA_WLEN_C);
4020
13.9k
  register_set_handler_capability_spinel(
4021
13.9k
    kWPANTUNDProperty_CommissionerSendMgmtSet,
4022
13.9k
    SPINEL_CAP_THREAD_COMMISSIONER,
4023
13.9k
    SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_SET, SPINEL_DATATYPE_DATA_WLEN_C);
4024
13.9k
  register_set_handler_capability_spinel(
4025
13.9k
    kWPANTUNDProperty_ChannelManagerChannelSelect,
4026
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
4027
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_CHANNEL_SELECT, SPINEL_DATATYPE_BOOL_C);
4028
13.9k
  register_set_handler_capability_spinel(
4029
13.9k
    kWPANTUNDProperty_TimeSync_Period,
4030
13.9k
    SPINEL_CAP_TIME_SYNC,
4031
13.9k
    SPINEL_PROP_TIME_SYNC_PERIOD, SPINEL_DATATYPE_UINT16_C);
4032
13.9k
  register_set_handler_capability_spinel(
4033
13.9k
    kWPANTUNDProperty_TimeSync_XtalThreshold,
4034
13.9k
    SPINEL_CAP_TIME_SYNC,
4035
13.9k
    SPINEL_PROP_TIME_SYNC_XTAL_THRESHOLD, SPINEL_DATATYPE_UINT16_C);
4036
13.9k
  register_set_handler_capability_spinel(
4037
13.9k
    kWPANTUNDProperty_OpenThreadLogTimestampBase,
4038
13.9k
    SPINEL_CAP_OPENTHREAD_LOG_METADATA,
4039
13.9k
    SPINEL_PROP_DEBUG_LOG_TIMESTAMP_BASE, SPINEL_DATATYPE_UINT64_C);
4040
13.9k
  register_set_handler_capability_spinel(
4041
13.9k
    kWPANTUNDProperty_ThreadDomainName,
4042
13.9k
    SPINEL_CAP_NET_THREAD_1_2,
4043
13.9k
    SPINEL_PROP_THREAD_DOMAIN_NAME,
4044
13.9k
    SPINEL_DATATYPE_UTF8_C);
4045
4046
13.9k
  register_set_handler_capability_spinel(
4047
13.9k
    kWPANTUNDProperty_ThreadCslPeriod,
4048
13.9k
    SPINEL_CAP_THREAD_CSL_RECEIVER,
4049
13.9k
    SPINEL_PROP_THREAD_CSL_PERIOD, SPINEL_DATATYPE_UINT16_C);
4050
13.9k
  register_set_handler_capability_spinel(
4051
13.9k
    kWPANTUNDProperty_ThreadCslTimeout,
4052
13.9k
    SPINEL_CAP_THREAD_CSL_RECEIVER,
4053
13.9k
    SPINEL_PROP_THREAD_CSL_TIMEOUT, SPINEL_DATATYPE_UINT32_C);
4054
13.9k
  register_set_handler_capability_spinel(
4055
13.9k
    kWPANTUNDProperty_ThreadCslChannel,
4056
13.9k
    SPINEL_CAP_THREAD_CSL_RECEIVER,
4057
13.9k
    SPINEL_PROP_THREAD_CSL_CHANNEL, SPINEL_DATATYPE_UINT8_C);
4058
13.9k
  register_set_handler_capability_spinel(
4059
13.9k
    kWPANTUNDProperty_ThreadBackboneRouterLocalJitter,
4060
13.9k
    SPINEL_CAP_THREAD_BACKBONE_ROUTER,
4061
13.9k
    SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER, SPINEL_DATATYPE_UINT8_C);
4062
4063
  // Properties with a `ValueConverter`
4064
13.9k
  register_set_handler_capability_spinel(
4065
13.9k
    kWPANTUNDProperty_CommissionerState,
4066
13.9k
    SPINEL_CAP_THREAD_COMMISSIONER,
4067
13.9k
    SPINEL_PROP_MESHCOP_COMMISSIONER_STATE, SPINEL_DATATYPE_UINT8_C,
4068
13.9k
    &SpinelNCPInstance::convert_value_CommissionerState);
4069
13.9k
  register_set_handler_capability_spinel(
4070
13.9k
    kWPANTUNDProperty_NCPCounterAllReset,
4071
13.9k
    SPINEL_CAP_COUNTERS,
4072
13.9k
    SPINEL_PROP_CNTR_RESET, SPINEL_DATATYPE_UINT8_C,
4073
13.9k
    &SpinelNCPInstance::convert_value_counter_reset);
4074
13.9k
  register_set_handler_capability_spinel(
4075
13.9k
    kWPANTUNDProperty_NCPCounterAllMac,
4076
13.9k
    SPINEL_CAP_COUNTERS,
4077
13.9k
    SPINEL_PROP_CNTR_ALL_MAC_COUNTERS, SPINEL_DATATYPE_UINT8_C,
4078
13.9k
    &SpinelNCPInstance::convert_value_counter_reset);
4079
13.9k
  register_set_handler_capability_spinel(
4080
13.9k
    kWPANTUNDProperty_NCPCounterThreadMle,
4081
13.9k
    SPINEL_CAP_COUNTERS,
4082
13.9k
    SPINEL_PROP_CNTR_MLE_COUNTERS, SPINEL_DATATYPE_UINT8_C,
4083
13.9k
    &SpinelNCPInstance::convert_value_counter_reset);
4084
13.9k
  register_set_handler_capability_spinel(
4085
13.9k
    kWPANTUNDProperty_NCPCounterAllIPv6,
4086
13.9k
    SPINEL_CAP_COUNTERS,
4087
13.9k
    SPINEL_PROP_CNTR_ALL_IP_COUNTERS, SPINEL_DATATYPE_UINT8_C,
4088
13.9k
    &SpinelNCPInstance::convert_value_counter_reset);
4089
13.9k
  register_set_handler_capability_spinel(
4090
13.9k
    kWPANTUNDProperty_ThreadDUAInterfaceIdentifier,
4091
13.9k
    SPINEL_CAP_DUA,
4092
13.9k
    SPINEL_PROP_THREAD_DUA_ID, SPINEL_DATATYPE_DATA_C,
4093
13.9k
    &SpinelNCPInstance::convert_value_dua_interface_identifier);
4094
13.9k
  register_set_handler_capability_spinel(
4095
13.9k
    kWPANTUNDProperty_ThreadBackboneRouterLocalState,
4096
13.9k
    SPINEL_CAP_THREAD_BACKBONE_ROUTER,
4097
13.9k
    SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE, SPINEL_DATATYPE_UINT8_C,
4098
13.9k
    &SpinelNCPInstance::convert_value_BackboneRouterState);
4099
13.9k
  register_set_handler_capability_spinel(
4100
13.9k
    kWPANTUNDProperty_ThreadBackboneRouterLocalRegister,
4101
13.9k
    SPINEL_CAP_THREAD_BACKBONE_ROUTER,
4102
13.9k
    SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTER, SPINEL_DATATYPE_UINT8_C,
4103
13.9k
    &SpinelNCPInstance::convert_value_BackboneRouterRegister);
4104
4105
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4106
  // Properties requiring capability check and persistence (saving in settings),
4107
  // and associated with a spinel property
4108
4109
13.9k
  register_set_handler_capability_spinel_persist(
4110
13.9k
    kWPANTUNDProperty_NCPSleepyPollInterval,
4111
13.9k
    SPINEL_CAP_ROLE_SLEEPY,
4112
13.9k
    SPINEL_PROP_MAC_DATA_POLL_PERIOD, SPINEL_DATATYPE_UINT32_C);
4113
13.9k
  register_set_handler_capability_spinel_persist(
4114
13.9k
    kWPANTUNDProperty_TmfProxyEnabled,
4115
13.9k
    SPINEL_CAP_THREAD_TMF_PROXY,
4116
13.9k
    SPINEL_PROP_THREAD_TMF_PROXY_ENABLED, SPINEL_DATATYPE_BOOL_C);
4117
13.9k
  register_set_handler_capability_spinel_persist(
4118
13.9k
    kWPANTUNDProperty_JamDetectionEnable,
4119
13.9k
    SPINEL_CAP_JAM_DETECT,
4120
13.9k
    SPINEL_PROP_JAM_DETECT_ENABLE, SPINEL_DATATYPE_BOOL_C);
4121
13.9k
  register_set_handler_capability_spinel_persist(
4122
13.9k
    kWPANTUNDProperty_JamDetectionRssiThreshold,
4123
13.9k
    SPINEL_CAP_JAM_DETECT,
4124
13.9k
    SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD, SPINEL_DATATYPE_INT8_C);
4125
13.9k
  register_set_handler_capability_spinel_persist(
4126
13.9k
    kWPANTUNDProperty_JamDetectionWindow,
4127
13.9k
    SPINEL_CAP_JAM_DETECT,
4128
13.9k
    SPINEL_PROP_JAM_DETECT_WINDOW, SPINEL_DATATYPE_UINT8_C);
4129
13.9k
  register_set_handler_capability_spinel_persist(
4130
13.9k
    kWPANTUNDProperty_JamDetectionBusyPeriod,
4131
13.9k
    SPINEL_CAP_JAM_DETECT,
4132
13.9k
    SPINEL_PROP_JAM_DETECT_BUSY, SPINEL_DATATYPE_UINT8_C);
4133
13.9k
  register_set_handler_capability_spinel_persist(
4134
13.9k
    kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix,
4135
13.9k
    SPINEL_CAP_NEST_LEGACY_INTERFACE,
4136
13.9k
    SPINEL_PROP_NEST_LEGACY_ULA_PREFIX, SPINEL_DATATYPE_DATA_C);
4137
13.9k
  register_set_handler_capability_spinel_persist(
4138
13.9k
    kWPANTUNDProperty_ChildSupervisionInterval,
4139
13.9k
    SPINEL_CAP_CHILD_SUPERVISION,
4140
13.9k
    SPINEL_PROP_CHILD_SUPERVISION_INTERVAL, SPINEL_DATATYPE_UINT16_C);
4141
13.9k
  register_set_handler_capability_spinel_persist(
4142
13.9k
    kWPANTUNDProperty_ChildSupervisionCheckTimeout,
4143
13.9k
    SPINEL_CAP_CHILD_SUPERVISION,
4144
13.9k
    SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT, SPINEL_DATATYPE_UINT16_C);
4145
13.9k
  register_set_handler_capability_spinel_persist(
4146
13.9k
    kWPANTUNDProperty_ChannelManagerNewChannel,
4147
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
4148
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL, SPINEL_DATATYPE_UINT8_C);
4149
13.9k
  register_set_handler_capability_spinel_persist(
4150
13.9k
    kWPANTUNDProperty_ChannelManagerDelay,
4151
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
4152
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_DELAY, SPINEL_DATATYPE_UINT16_C);
4153
13.9k
  register_set_handler_capability_spinel_persist(
4154
13.9k
    kWPANTUNDProperty_ChannelManagerAutoSelectEnabled,
4155
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
4156
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_ENABLED, SPINEL_DATATYPE_BOOL_C);
4157
13.9k
  register_set_handler_capability_spinel_persist(
4158
13.9k
    kWPANTUNDProperty_ChannelManagerAutoSelectInterval,
4159
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
4160
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_INTERVAL, SPINEL_DATATYPE_UINT32_C);
4161
13.9k
  register_set_handler_capability_spinel_persist(
4162
13.9k
    kWPANTUNDProperty_OpenThreadSLAACEnabled,
4163
13.9k
    SPINEL_CAP_SLAAC,
4164
13.9k
    SPINEL_PROP_SLAAC_ENABLED, SPINEL_DATATYPE_BOOL_C);
4165
13.9k
  register_set_handler_capability_spinel_persist(
4166
13.9k
    kWPANTUNDProperty_NCPCoexEnable,
4167
13.9k
    SPINEL_CAP_RADIO_COEX,
4168
13.9k
    SPINEL_PROP_RADIO_COEX_ENABLE, SPINEL_DATATYPE_BOOL_C);
4169
4170
  // Properties with a `ValueConverter`
4171
13.9k
  register_set_handler_capability_spinel_persist(
4172
13.9k
    kWPANTUNDProperty_NCPMCUPowerState,
4173
13.9k
    SPINEL_PROP_MCU_POWER_STATE,
4174
13.9k
    SPINEL_PROP_MCU_POWER_STATE, SPINEL_DATATYPE_UINT8_C,
4175
13.9k
    &SpinelNCPInstance::convert_value_NCPMCUPowerState);
4176
13.9k
  register_set_handler_capability_spinel_persist(
4177
13.9k
    kWPANTUNDProperty_ChannelManagerSupportedChannelMask,
4178
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
4179
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS, SPINEL_DATATYPE_DATA_C,
4180
13.9k
    &SpinelNCPInstance::convert_value_channel_mask);
4181
13.9k
  register_set_handler_capability_spinel_persist(
4182
13.9k
    kWPANTUNDProperty_ChannelManagerFavoredChannelMask,
4183
13.9k
    SPINEL_CAP_CHANNEL_MANAGER,
4184
13.9k
    SPINEL_PROP_CHANNEL_MANAGER_FAVORED_CHANNELS, SPINEL_DATATYPE_DATA_C,
4185
13.9k
    &SpinelNCPInstance::convert_value_channel_mask);
4186
4187
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4188
  // Properties with a dedicated handler method
4189
4190
13.9k
  register_set_handler(
4191
13.9k
    kWPANTUNDProperty_NetworkKey,
4192
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_NetworkKey, this, _1, _2));
4193
13.9k
  register_set_handler(
4194
13.9k
    kWPANTUNDProperty_InterfaceUp,
4195
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_InterfaceUp, this, _1, _2));
4196
13.9k
  register_set_handler(
4197
13.9k
    kWPANTUNDProperty_NetworkXPANID,
4198
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_NetworkXPANID, this, _1, _2));
4199
13.9k
  register_set_handler(
4200
13.9k
    kWPANTUNDProperty_IPv6MeshLocalPrefix,
4201
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_IPv6MeshLocalPrefix, this, _1, _2));
4202
13.9k
  register_set_handler(
4203
13.9k
    kWPANTUNDProperty_ThreadConfigFilterRLOCAddresses,
4204
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_ThreadConfigFilterRLOCAddresses, this, _1, _2));
4205
13.9k
  register_set_handler(
4206
13.9k
    kWPANTUNDProperty_ThreadConfigFilterALOCAddresses,
4207
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_ThreadConfigFilterALOCAddresses, this, _1, _2));
4208
13.9k
  register_set_handler(
4209
13.9k
    kWPANTUNDProperty_OpenThreadSteeringDataSetWhenJoinable,
4210
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_OpenThreadSteeringDataSetWhenJoinable, this, _1, _2));
4211
13.9k
  register_set_handler(
4212
13.9k
    kWPANTUNDProperty_OpenThreadSteeringDataAddress,
4213
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_OpenThreadSteeringDataAddress, this, _1, _2));
4214
13.9k
  register_set_handler(
4215
13.9k
    kWPANTUNDProperty_TmfProxyStream,
4216
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_TmfProxyStream, this, _1, _2));
4217
13.9k
  register_set_handler(
4218
13.9k
    kWPANTUNDProperty_UdpForwardStream,
4219
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_UdpForwardStream, this, _1, _2));
4220
13.9k
  register_set_handler(
4221
13.9k
    kWPANTUNDProperty_DatasetActiveTimestamp,
4222
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetActiveTimestamp, this, _1, _2));
4223
13.9k
  register_set_handler(
4224
13.9k
    kWPANTUNDProperty_DatasetPendingTimestamp,
4225
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetPendingTimestamp, this, _1, _2));
4226
13.9k
  register_set_handler(
4227
13.9k
    kWPANTUNDProperty_DatasetMasterKey,
4228
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetMasterKey, this, _1, _2));
4229
13.9k
  register_set_handler(
4230
13.9k
    kWPANTUNDProperty_DatasetNetworkName,
4231
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetNetworkName, this, _1, _2));
4232
13.9k
  register_set_handler(
4233
13.9k
    kWPANTUNDProperty_DatasetExtendedPanId,
4234
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetExtendedPanId, this, _1, _2));
4235
13.9k
  register_set_handler(
4236
13.9k
    kWPANTUNDProperty_DatasetMeshLocalPrefix,
4237
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetMeshLocalPrefix, this, _1, _2));
4238
13.9k
  register_set_handler(
4239
13.9k
    kWPANTUNDProperty_DatasetDelay,
4240
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetDelay, this, _1, _2));
4241
13.9k
  register_set_handler(
4242
13.9k
    kWPANTUNDProperty_DatasetPanId,
4243
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetPanId, this, _1, _2));
4244
13.9k
  register_set_handler(
4245
13.9k
    kWPANTUNDProperty_DatasetChannel,
4246
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetChannel, this, _1, _2));
4247
13.9k
  register_set_handler(
4248
13.9k
    kWPANTUNDProperty_DatasetPSKc,
4249
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetPSKc, this, _1, _2));
4250
13.9k
  register_set_handler(
4251
13.9k
    kWPANTUNDProperty_DatasetChannelMaskPage0,
4252
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetChannelMaskPage0, this, _1, _2));
4253
13.9k
  register_set_handler(
4254
13.9k
    kWPANTUNDProperty_DatasetSecPolicyKeyRotation,
4255
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetSecPolicyKeyRotation, this, _1, _2));
4256
13.9k
  register_set_handler(
4257
13.9k
    kWPANTUNDProperty_DatasetSecPolicyFlags,
4258
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetSecPolicyFlags, this, _1, _2));
4259
13.9k
  register_set_handler(
4260
13.9k
    kWPANTUNDProperty_DatasetRawTlvs,
4261
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetRawTlvs, this, _1, _2));
4262
13.9k
  register_set_handler(
4263
13.9k
    kWPANTUNDProperty_DatasetDestIpAddress,
4264
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetDestIpAddress, this, _1, _2));
4265
13.9k
  register_set_handler(
4266
13.9k
    kWPANTUNDProperty_DatasetCommand,
4267
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DatasetCommand, this, _1, _2));
4268
13.9k
  register_set_handler(
4269
13.9k
    kWPANTUNDProperty_DaemonTickleOnHostDidWake,
4270
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_DaemonTickleOnHostDidWake, this, _1, _2));
4271
13.9k
  register_set_handler(
4272
13.9k
    kWPANTUNDProperty_MACFilterFixedRssi,
4273
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_MACFilterFixedRssi, this, _1, _2));
4274
13.9k
  register_set_handler(
4275
13.9k
    kWPANTUNDProperty_JoinerDiscernerBitLength,
4276
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_JoinerDiscernerBitLength, this, _1, _2));
4277
13.9k
  register_set_handler(
4278
13.9k
    kWPANTUNDProperty_JoinerDiscernerValue,
4279
13.9k
    boost::bind(&SpinelNCPInstance::set_prop_JoinerDiscernerValue, this, _1, _2));
4280
13.9k
}
4281
4282
int
4283
SpinelNCPInstance::convert_value_NCPMCUPowerState(const boost::any &value, boost::any &value_out)
4284
502
{
4285
502
  int ret = kWPANTUNDStatus_Ok;
4286
502
  std::string str = any_to_string(value);
4287
4288
502
  if (strcaseequal(str.c_str(), kWPANTUNDNCPMCUPowerState_On)) {
4289
10
    value_out = static_cast<uint8_t>(SPINEL_MCU_POWER_STATE_ON);
4290
492
  } else if (strcaseequal(str.c_str(), kWPANTUNDNCPMCUPowerState_LowPower) || strcaseequal(str.c_str(), "lp")) {
4291
248
    value_out = static_cast<uint8_t>(SPINEL_MCU_POWER_STATE_LOW_POWER);
4292
248
  } else if (strcaseequal(str.c_str(), "kWPANTUNDNCPMCUPowerState_Off")) {
4293
1
    value_out = static_cast<uint8_t>(SPINEL_MCU_POWER_STATE_OFF);
4294
243
  } else {
4295
243
    ret = kWPANTUNDStatus_InvalidArgument;
4296
243
  }
4297
4298
502
  return ret;
4299
502
}
4300
4301
int
4302
SpinelNCPInstance::convert_value_channel_mask(const boost::any &value, boost::any &value_out)
4303
78
{
4304
78
  uint32_t channel_mask = any_to_int(value);
4305
78
  Data mask_array(32);
4306
4307
78
  mask_array.clear();
4308
2.57k
  for (uint8_t channel = 0; channel < 32; channel++) {
4309
2.49k
    if (channel_mask & (1U << channel)) {
4310
544
      mask_array.push_back(channel);
4311
544
    }
4312
2.49k
  }
4313
4314
78
  value_out = mask_array;
4315
78
  return kWPANTUNDStatus_Ok;
4316
78
}
4317
4318
int
4319
SpinelNCPInstance::convert_value_counter_reset(const boost::any &value, boost::any &value_out)
4320
13
{
4321
  // When reseting all/subset of counters, the value written to
4322
  // related spinel property does not matter, so we just write
4323
  // value `1`.
4324
4325
13
  (void)value;
4326
13
  value_out = 1;
4327
13
  return kWPANTUNDStatus_Ok;
4328
13
}
4329
4330
int
4331
SpinelNCPInstance::convert_value_CommissionerState(const boost::any &value, boost::any &value_out)
4332
258
{
4333
258
  int ret = kWPANTUNDStatus_Ok;
4334
258
  std::string state_str = any_to_string(value);
4335
258
  const char *str = state_str.c_str();
4336
4337
258
  if (strcaseequal(str, kWPANTUNDCommissionerState_Disabled) || strcaseequal(str, "stop") || strcaseequal(str, "off")
4338
251
    || strcaseequal(str, "0") || strcaseequal(str, "false")
4339
258
  ) {
4340
9
    value_out = static_cast<uint8_t>(SPINEL_MESHCOP_COMMISSIONER_STATE_DISABLED);
4341
4342
249
  } else if (strcaseequal(str, kWPANTUNDCommissionerState_Active) || strcaseequal(str, "start") ||
4343
240
    strcaseequal(str, "on") || strcaseequal(str, "1") || strcaseequal(str, "true")
4344
249
  ) {
4345
23
    value_out = static_cast<uint8_t>(SPINEL_MESHCOP_COMMISSIONER_STATE_ACTIVE);
4346
4347
226
  } else {
4348
226
    ret = kWPANTUNDStatus_InvalidArgument;
4349
226
  }
4350
4351
258
  return ret;
4352
258
}
4353
4354
int
4355
SpinelNCPInstance::convert_value_dua_interface_identifier(const boost::any &value, boost::any &value_out)
4356
0
{
4357
0
  std::string state_str = any_to_string(value);
4358
0
  Data data;
4359
0
  int ret = kWPANTUNDStatus_Ok;
4360
4361
0
  if (state_str.length() == 16)
4362
0
  {
4363
0
    data.resize(8);
4364
0
    parse_string_into_data(data.data(), data.size(), state_str.c_str());
4365
0
  }
4366
0
  else if (state_str.length() != 0)
4367
0
  {
4368
0
    ret = kWPANTUNDStatus_InvalidArgument;
4369
0
  }
4370
0
  else
4371
0
  {
4372
    // Intentionally leave empty data when state_str.length() == 0
4373
0
  }
4374
4375
0
  value_out = data;
4376
0
  return ret;
4377
0
}
4378
4379
int
4380
SpinelNCPInstance::convert_value_BackboneRouterState(const boost::any &value, boost::any &value_out)
4381
337
{
4382
337
  int ret = kWPANTUNDStatus_Ok;
4383
337
  std::string state_str = any_to_string(value);
4384
337
  const char *str = state_str.c_str();
4385
4386
337
  if (strcaseequal(str, kWPANTUNDThreadBackboneRouterState_Disabled) || strcaseequal(str, "stop") || strcaseequal(str, "off")
4387
333
    || strcaseequal(str, "0") || strcaseequal(str, "false") || strcaseequal(str, "disable")
4388
337
  ) {
4389
31
    value_out = static_cast<uint8_t>(SPINEL_THREAD_BACKBONE_ROUTER_STATE_DISABLED);
4390
4391
306
  } else if (strcaseequal(str, kWPANTUNDThreadBackboneRouterState_Primary) || strcaseequal(str, "start") ||
4392
281
    strcaseequal(str, "on") || strcaseequal(str, "1") || strcaseequal(str, "true") || strcaseequal(str, "enable")
4393
306
  ) {
4394
41
    value_out = static_cast<uint8_t>(SPINEL_THREAD_BACKBONE_ROUTER_STATE_PRIMARY);
4395
4396
265
  } else {
4397
265
    ret = kWPANTUNDStatus_InvalidArgument;
4398
265
  }
4399
4400
337
  return ret;
4401
337
}
4402
4403
int
4404
SpinelNCPInstance::convert_value_BackboneRouterRegister(const boost::any &value, boost::any &value_out)
4405
0
{
4406
  // The value written to related spinel property does not matter,
4407
  // so we just write value `1`.
4408
4409
0
  (void)value;
4410
0
  value_out = 1;
4411
0
  return kWPANTUNDStatus_Ok;
4412
0
}
4413
4414
void
4415
SpinelNCPInstance::set_prop_NetworkKey(const boost::any &value, CallbackWithStatus cb)
4416
69
{
4417
69
  Data network_key = any_to_data(value);
4418
4419
69
  if (!ncp_state_is_joining_or_joined(get_ncp_state())) {
4420
69
    mNetworkKey = network_key;
4421
69
    if (mNetworkKeyIndex == 0) {
4422
56
      mNetworkKeyIndex = 1;
4423
56
    }
4424
69
  }
4425
4426
69
  if (get_ncp_state() == CREDENTIALS_NEEDED) {
4427
0
    ValueMap options;
4428
0
    options[kWPANTUNDProperty_NetworkKey] = value;
4429
0
    start_new_task(boost::shared_ptr<SpinelNCPTask>(
4430
0
      new SpinelNCPTaskJoin(
4431
0
        this,
4432
0
        boost::bind(cb,_1),
4433
0
        options
4434
0
      )
4435
0
    ));
4436
69
  } else {
4437
69
    set_spinel_prop(value, cb, SPINEL_PROP_NET_MASTER_KEY, SPINEL_DATATYPE_DATA_C);
4438
69
  }
4439
69
}
4440
4441
void
4442
SpinelNCPInstance::set_prop_InterfaceUp(const boost::any &value, CallbackWithStatus cb)
4443
202
{
4444
202
  bool isup = any_to_bool(value);
4445
4446
202
  if (isup) {
4447
95
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
4448
95
      .set_callback(cb)
4449
95
      .add_command(SpinelPackData(
4450
95
        SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
4451
95
        SPINEL_PROP_NET_IF_UP,
4452
95
        true
4453
95
      ))
4454
95
      .add_command(SpinelPackData(
4455
95
        SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
4456
95
        SPINEL_PROP_NET_STACK_UP,
4457
95
        true
4458
95
      ))
4459
95
      .finish()
4460
95
    );
4461
107
  } else {
4462
107
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
4463
107
      .set_callback(cb)
4464
107
      .add_command(SpinelPackData(
4465
107
        SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
4466
107
        SPINEL_PROP_NET_STACK_UP,
4467
107
        false
4468
107
      ))
4469
107
      .add_command(SpinelPackData(
4470
107
        SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
4471
107
        SPINEL_PROP_NET_IF_UP,
4472
107
        false
4473
107
      ))
4474
107
      .finish()
4475
107
    );
4476
107
  }
4477
202
}
4478
4479
void
4480
SpinelNCPInstance::set_prop_NetworkXPANID(const boost::any &value, CallbackWithStatus cb)
4481
18
{
4482
18
  mXPANIDWasExplicitlySet = true;
4483
18
  set_spinel_prop(value, cb, SPINEL_PROP_NET_XPANID, SPINEL_DATATYPE_DATA_C);
4484
18
}
4485
4486
void
4487
SpinelNCPInstance::set_prop_IPv6MeshLocalPrefix(const boost::any &value, CallbackWithStatus cb)
4488
10
{
4489
10
  struct in6_addr addr = any_to_ipv6(value);
4490
4491
10
  start_new_task(SpinelNCPTaskSendCommand::Factory(this)
4492
10
    .set_callback(cb)
4493
10
    .add_command(SpinelPackData(
4494
10
      SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_IPv6ADDR_S SPINEL_DATATYPE_UINT8_S),
4495
10
      SPINEL_PROP_IPV6_ML_PREFIX,
4496
10
      &addr,
4497
10
      64
4498
10
    ))
4499
10
    .finish()
4500
10
  );
4501
10
}
4502
4503
void
4504
SpinelNCPInstance::set_prop_ThreadConfigFilterRLOCAddresses(const boost::any &value, CallbackWithStatus cb)
4505
0
{
4506
0
  mFilterRLOCAddresses = any_to_bool(value);
4507
0
  cb(kWPANTUNDStatus_Ok);
4508
0
}
4509
4510
void
4511
SpinelNCPInstance::set_prop_ThreadConfigFilterALOCAddresses(const boost::any &value, CallbackWithStatus cb)
4512
0
{
4513
0
  mFilterALOCAddresses = any_to_bool(value);
4514
0
  cb(kWPANTUNDStatus_Ok);
4515
0
}
4516
4517
void
4518
SpinelNCPInstance::set_prop_OpenThreadSteeringDataSetWhenJoinable(const boost::any &value, CallbackWithStatus cb)
4519
10
{
4520
10
  mSetSteeringDataWhenJoinable = any_to_bool(value);
4521
10
  cb(kWPANTUNDStatus_Ok);
4522
10
}
4523
4524
void
4525
SpinelNCPInstance::set_prop_OpenThreadSteeringDataAddress(const boost::any &value, CallbackWithStatus cb)
4526
14
{
4527
14
  Data address = any_to_data(value);
4528
14
  wpantund_status_t status = kWPANTUNDStatus_Ok;
4529
4530
14
  if (address.size() != sizeof(mSteeringDataAddress)) {
4531
13
    status = kWPANTUNDStatus_InvalidArgument;
4532
13
  } else {
4533
1
    memcpy(mSteeringDataAddress, address.data(), sizeof(mSteeringDataAddress));
4534
1
  }
4535
4536
14
  cb (status);
4537
14
}
4538
4539
void
4540
SpinelNCPInstance::set_prop_TmfProxyStream(const boost::any &value, CallbackWithStatus cb)
4541
15
{
4542
15
  Data packet = any_to_data(value);
4543
4544
15
  if (packet.size() > sizeof(uint16_t)*2) {
4545
11
    uint16_t port = (packet[packet.size() - sizeof(port)] << 8 | packet[packet.size() - sizeof(port) + 1]);
4546
11
    uint16_t locator = (packet[packet.size() - sizeof(locator) - sizeof(port)] << 8 |
4547
11
        packet[packet.size() - sizeof(locator) - sizeof(port) + 1]);
4548
4549
11
    packet.resize(packet.size() - sizeof(locator) - sizeof(port));
4550
4551
11
    Data command = SpinelPackData(
4552
11
      SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(
4553
11
        SPINEL_DATATYPE_DATA_WLEN_S
4554
11
        SPINEL_DATATYPE_UINT16_S
4555
11
        SPINEL_DATATYPE_UINT16_S
4556
11
      ),
4557
11
      SPINEL_PROP_THREAD_TMF_PROXY_STREAM,
4558
11
      packet.data(),
4559
11
      packet.size(),
4560
11
      locator,
4561
11
      port
4562
11
    );
4563
4564
11
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
4565
11
      .set_callback(cb)
4566
11
      .add_command(command)
4567
11
      .finish()
4568
11
    );
4569
11
  } else {
4570
4
    cb(kWPANTUNDStatus_InvalidArgument);
4571
4
  }
4572
15
}
4573
4574
void
4575
SpinelNCPInstance::set_prop_UdpForwardStream(const boost::any &value, CallbackWithStatus cb)
4576
29
{
4577
29
  Data packet = any_to_data(value);
4578
4579
29
  if (packet.size() > sizeof(uint16_t) * 2 + sizeof(in6_addr)) {
4580
12
    in6_addr peer_addr;
4581
12
    const size_t payload_len = packet.size() - sizeof(uint16_t) * 2 - sizeof(struct in6_addr);
4582
12
    size_t i = payload_len;
4583
12
    const uint16_t peer_port = (packet[i] << 8 | packet[i + 1]);
4584
12
    i += sizeof(uint16_t);
4585
12
    memcpy(peer_addr.s6_addr, &packet[i], sizeof(peer_addr));
4586
12
    i += sizeof(peer_addr);
4587
12
    const uint16_t sock_port = (packet[i] << 8 | packet[i + 1]);
4588
4589
12
    Data command = SpinelPackData(
4590
12
      SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(
4591
12
        SPINEL_DATATYPE_DATA_WLEN_S
4592
12
        SPINEL_DATATYPE_UINT16_S    // Peer port
4593
12
        SPINEL_DATATYPE_IPv6ADDR_S  // Peer address
4594
12
        SPINEL_DATATYPE_UINT16_S    // Sock port
4595
12
      ),
4596
12
      SPINEL_PROP_THREAD_UDP_FORWARD_STREAM,
4597
12
      packet.data(),
4598
12
      payload_len,
4599
12
      peer_port,
4600
12
      &peer_addr,
4601
12
      sock_port
4602
12
    );
4603
4604
12
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
4605
12
      .set_callback(cb)
4606
12
      .add_command(command)
4607
12
      .finish()
4608
12
    );
4609
17
  } else {
4610
17
    cb(kWPANTUNDStatus_InvalidArgument);
4611
17
  }
4612
29
}
4613
4614
void
4615
SpinelNCPInstance::set_prop_DatasetActiveTimestamp(const boost::any &value, CallbackWithStatus cb)
4616
14
{
4617
14
    mLocalDataset.mActiveTimestamp = any_to_uint64(value);
4618
14
    cb(kWPANTUNDStatus_Ok);
4619
14
}
4620
4621
void
4622
SpinelNCPInstance::set_prop_DatasetPendingTimestamp(const boost::any &value, CallbackWithStatus cb)
4623
30
{
4624
30
  mLocalDataset.mPendingTimestamp = any_to_uint64(value);
4625
30
  cb(kWPANTUNDStatus_Ok);
4626
30
}
4627
4628
void
4629
SpinelNCPInstance::set_prop_DatasetMasterKey(const boost::any &value, CallbackWithStatus cb)
4630
20
{
4631
20
  Data master_key = any_to_data(value);
4632
4633
20
  if (master_key.size() == NCP_NETWORK_KEY_SIZE) {
4634
9
    mLocalDataset.mMasterKey = master_key;
4635
9
    cb(kWPANTUNDStatus_Ok);
4636
11
  } else {
4637
11
    cb(kWPANTUNDStatus_InvalidArgument);
4638
11
  }
4639
20
}
4640
4641
void
4642
SpinelNCPInstance::set_prop_DatasetNetworkName(const boost::any &value, CallbackWithStatus cb)
4643
63
{
4644
63
  mLocalDataset.mNetworkName = any_to_string(value);
4645
63
  cb(kWPANTUNDStatus_Ok);
4646
63
}
4647
4648
void
4649
SpinelNCPInstance::set_prop_DatasetExtendedPanId(const boost::any &value, CallbackWithStatus cb)
4650
24
{
4651
24
  Data xpanid = any_to_data(value);
4652
4653
24
  if (xpanid.size() == sizeof(spinel_net_xpanid_t)) {
4654
14
    mLocalDataset.mExtendedPanId = any_to_data(value);
4655
14
    cb(kWPANTUNDStatus_Ok);
4656
14
  } else {
4657
10
    cb(kWPANTUNDStatus_InvalidArgument);
4658
10
  }
4659
24
}
4660
4661
void
4662
SpinelNCPInstance::set_prop_DatasetMeshLocalPrefix(const boost::any &value, CallbackWithStatus cb)
4663
63
{
4664
63
  mLocalDataset.mMeshLocalPrefix = any_to_ipv6(value);
4665
63
  cb(kWPANTUNDStatus_Ok);
4666
63
}
4667
4668
void
4669
SpinelNCPInstance::set_prop_DatasetDelay(const boost::any &value, CallbackWithStatus cb)
4670
26
{
4671
26
  mLocalDataset.mDelay = static_cast<uint32_t>(any_to_int(value));
4672
26
  cb(kWPANTUNDStatus_Ok);
4673
26
}
4674
4675
void
4676
SpinelNCPInstance::set_prop_DatasetPanId(const boost::any &value, CallbackWithStatus cb)
4677
21
{
4678
21
  mLocalDataset.mPanId = static_cast<uint16_t>(any_to_int(value));
4679
21
  cb(kWPANTUNDStatus_Ok);
4680
21
}
4681
4682
void
4683
SpinelNCPInstance::set_prop_DatasetChannel(const boost::any &value, CallbackWithStatus cb)
4684
25
{
4685
25
  mLocalDataset.mChannel = static_cast<uint8_t>(any_to_int(value));
4686
25
  cb(kWPANTUNDStatus_Ok);
4687
25
}
4688
4689
void
4690
SpinelNCPInstance::set_prop_DatasetPSKc(const boost::any &value, CallbackWithStatus cb)
4691
69
{
4692
69
  Data pskc = any_to_data(value);
4693
4694
69
  if (pskc.size() <= sizeof(spinel_net_pskc_t)) {
4695
50
    mLocalDataset.mPSKc = any_to_data(value);
4696
50
    cb(kWPANTUNDStatus_Ok);
4697
50
  } else {
4698
19
    cb(kWPANTUNDStatus_InvalidArgument);
4699
19
  }
4700
69
}
4701
4702
void
4703
SpinelNCPInstance::set_prop_DatasetChannelMaskPage0(const boost::any &value, CallbackWithStatus cb)
4704
38
{
4705
38
  mLocalDataset.mChannelMaskPage0 = static_cast<uint32_t>(any_to_int(value));
4706
38
  cb(kWPANTUNDStatus_Ok);
4707
38
}
4708
4709
void
4710
SpinelNCPInstance::set_prop_DatasetSecPolicyKeyRotation(const boost::any &value, CallbackWithStatus cb)
4711
1
{
4712
1
  ThreadDataset::SecurityPolicy policy = mLocalDataset.mSecurityPolicy.get();
4713
1
  policy.mKeyRotationTime = static_cast<uint16_t>(any_to_int(value));
4714
1
  mLocalDataset.mSecurityPolicy = policy;
4715
1
  cb(kWPANTUNDStatus_Ok);
4716
1
}
4717
4718
void
4719
SpinelNCPInstance::set_prop_DatasetSecPolicyFlags(const boost::any &value, CallbackWithStatus cb)
4720
27
{
4721
27
  ThreadDataset::SecurityPolicy policy = mLocalDataset.mSecurityPolicy.get();
4722
27
  policy.mFlags = static_cast<uint8_t>(any_to_int(value));
4723
27
  mLocalDataset.mSecurityPolicy = policy;
4724
27
  cb(kWPANTUNDStatus_Ok);
4725
27
}
4726
4727
void
4728
SpinelNCPInstance::set_prop_DatasetRawTlvs(const boost::any &value, CallbackWithStatus cb)
4729
34
{
4730
34
  mLocalDataset.mRawTlvs = any_to_data(value);
4731
34
  cb(kWPANTUNDStatus_Ok);
4732
34
}
4733
4734
void
4735
SpinelNCPInstance::set_prop_DatasetDestIpAddress(const boost::any &value, CallbackWithStatus cb)
4736
56
{
4737
56
  mLocalDataset.mDestIpAddress = any_to_ipv6(value);
4738
56
  cb(kWPANTUNDStatus_Ok);
4739
56
}
4740
4741
void
4742
SpinelNCPInstance::set_prop_DatasetCommand(const boost::any &value, CallbackWithStatus cb)
4743
1.35k
{
4744
1.35k
  perform_dataset_command(any_to_string(value), cb);
4745
1.35k
}
4746
4747
void
4748
SpinelNCPInstance::set_prop_DaemonTickleOnHostDidWake(const boost::any &value, CallbackWithStatus cb)
4749
4
{
4750
4
  mTickleOnHostDidWake =  any_to_bool(value);
4751
4
  syslog(LOG_INFO, "TickleOnHostDidWake is %sabled", mTickleOnHostDidWake ? "en" : "dis");
4752
4
  cb(kWPANTUNDStatus_Ok);
4753
4
}
4754
4755
void
4756
SpinelNCPInstance::set_prop_MACFilterFixedRssi(const boost::any &value, CallbackWithStatus cb)
4757
1
{
4758
1
  if (mCapabilities.count(SPINEL_CAP_MAC_ALLOWLIST)) {
4759
0
    mMacFilterFixedRssi = static_cast<int8_t>(any_to_int(value));
4760
0
    cb(kWPANTUNDStatus_Ok);
4761
1
  } else {
4762
1
    cb(kWPANTUNDStatus_FeatureNotSupported);
4763
1
  }
4764
1
}
4765
4766
void
4767
SpinelNCPInstance::set_prop_JoinerDiscernerBitLength(const boost::any &value, CallbackWithStatus cb)
4768
0
{
4769
0
  if (mCapabilities.count(SPINEL_CAP_THREAD_JOINER)) {
4770
0
    mJoinerDiscernerBitLength = static_cast<uint8_t>(any_to_int(value));
4771
4772
    // Setting Discerner length to zero is to clear any previous set Discerner value
4773
0
    if (mJoinerDiscernerBitLength == 0) {
4774
4775
0
      start_new_task(SpinelNCPTaskSendCommand::Factory(this)
4776
0
        .set_callback(cb)
4777
0
        .add_command(SpinelPackData(
4778
0
          SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S),
4779
0
          SPINEL_PROP_MESHCOP_JOINER_DISCERNER,
4780
0
          mJoinerDiscernerBitLength
4781
0
        ))
4782
0
        .finish()
4783
0
      );
4784
4785
0
    } else {
4786
0
      cb(kWPANTUNDStatus_Ok);
4787
0
    }
4788
4789
0
  } else {
4790
0
    cb(kWPANTUNDStatus_FeatureNotSupported);
4791
0
  }
4792
0
}
4793
4794
void
4795
SpinelNCPInstance::set_prop_JoinerDiscernerValue(const boost::any &value, CallbackWithStatus cb)
4796
1
{
4797
1
  if (mCapabilities.count(SPINEL_CAP_THREAD_JOINER)) {
4798
0
    uint64_t discerner_value = any_to_uint64(value);
4799
4800
0
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
4801
0
      .set_callback(cb)
4802
0
      .add_command(SpinelPackData(
4803
0
        SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(
4804
0
          SPINEL_DATATYPE_UINT8_S
4805
0
          SPINEL_DATATYPE_UINT64_S
4806
0
        ),
4807
0
        SPINEL_PROP_MESHCOP_JOINER_DISCERNER,
4808
0
        mJoinerDiscernerBitLength,
4809
0
        discerner_value
4810
0
      ))
4811
0
      .finish()
4812
0
    );
4813
4814
1
  } else {
4815
1
    cb(kWPANTUNDStatus_FeatureNotSupported);
4816
1
  }
4817
1
}
4818
4819
void
4820
SpinelNCPInstance::property_set_value(
4821
  const std::string& key,
4822
  const boost::any& value,
4823
  CallbackWithStatus cb
4824
12.9k
) {
4825
12.9k
  syslog(LOG_INFO, "property_set_value: key: \"%s\"", key.c_str());
4826
4827
  // If we are disabled, then the only property we
4828
  // are allowed to set is kWPANTUNDProperty_DaemonEnabled.
4829
12.9k
  if (!mEnabled && !strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonEnabled)) {
4830
332
    cb(kWPANTUNDStatus_InvalidWhenDisabled);
4831
332
    return;
4832
332
  }
4833
4834
12.6k
  try {
4835
12.6k
    if (mVendorCustom.is_property_key_supported(key)) {
4836
0
      mVendorCustom.property_set_value(key, value, cb);
4837
4838
12.6k
    } else {
4839
12.6k
      NCPInstanceBase::property_set_value(key, value, cb);
4840
12.6k
    }
4841
4842
12.6k
  } catch (const boost::bad_any_cast &x) {
4843
    // We will get a bad_any_cast exception if the property is of
4844
    // the wrong type.
4845
0
    syslog(LOG_ERR,"property_set_value: Bad type for property \"%s\" (%s)", key.c_str(), x.what());
4846
0
    cb(kWPANTUNDStatus_InvalidArgument);
4847
0
  } catch (const std::invalid_argument &x) {
4848
    // We will get a bad_any_cast exception if the property is of
4849
    // the wrong type.
4850
0
    syslog(LOG_ERR,"property_set_value: Invalid argument for property \"%s\" (%s)", key.c_str(), x.what());
4851
0
    cb(kWPANTUNDStatus_InvalidArgument);
4852
0
  }
4853
12.6k
}
4854
4855
// ----------------------------------------------------------------------------
4856
// Property Insert Handlers
4857
4858
void
4859
SpinelNCPInstance::check_capability_prop_update(const boost::any &value, CallbackWithStatus cb,
4860
  const std::string &prop_name, unsigned int capability, PropUpdateHandler handler)
4861
0
{
4862
0
  if (mCapabilities.count(capability)) {
4863
0
    handler(value, cb, prop_name);
4864
0
  } else {
4865
0
    cb(kWPANTUNDStatus_FeatureNotSupported);
4866
0
  }
4867
0
}
4868
4869
void
4870
SpinelNCPInstance::register_insert_handler(const char *prop_name, PropUpdateHandler handler)
4871
41.8k
{
4872
41.8k
  NCPInstanceBase::register_prop_insert_handler(prop_name, handler);
4873
41.8k
}
4874
4875
void
4876
SpinelNCPInstance::register_insert_handler_capability(const char *prop_name, unsigned int capability,
4877
  PropUpdateHandler handler)
4878
41.8k
{
4879
41.8k
  register_insert_handler(
4880
41.8k
    prop_name,
4881
41.8k
    boost::bind(&SpinelNCPInstance::check_capability_prop_update, this, _1, _2, _3, capability, handler));
4882
41.8k
}
4883
4884
void
4885
SpinelNCPInstance::regsiter_all_insert_handlers(void)
4886
13.9k
{
4887
13.9k
  register_insert_handler_capability(
4888
13.9k
    kWPANTUNDProperty_MACAllowlistEntries,
4889
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
4890
13.9k
    boost::bind(&SpinelNCPInstance::insert_prop_MACAllowlistEntries, this, _1, _2));
4891
13.9k
  register_insert_handler_capability(
4892
13.9k
    kWPANTUNDProperty_MACDenylistEntries,
4893
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
4894
13.9k
    boost::bind(&SpinelNCPInstance::insert_prop_MACDenylistEntries, this, _1, _2));
4895
13.9k
  register_insert_handler_capability(
4896
13.9k
    kWPANTUNDProperty_MACFilterEntries,
4897
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
4898
13.9k
    boost::bind(&SpinelNCPInstance::insert_prop_MACFilterEntries, this, _1, _2));
4899
13.9k
}
4900
4901
void
4902
SpinelNCPInstance::insert_prop_MACAllowlistEntries(const boost::any &value, CallbackWithStatus cb)
4903
0
{
4904
0
  Data ext_address = any_to_data(value);
4905
0
  int8_t rssi = kWPANTUND_Allowlist_RssiOverrideDisabled;
4906
4907
0
  if (ext_address.size() == sizeof(spinel_eui64_t)) {
4908
0
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
4909
0
      .set_callback(cb)
4910
0
      .add_command(
4911
0
        SpinelPackData(
4912
0
          SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(SPINEL_DATATYPE_EUI64_S SPINEL_DATATYPE_INT8_S),
4913
0
          SPINEL_PROP_MAC_ALLOWLIST,
4914
0
          ext_address.data(),
4915
0
          rssi
4916
0
        )
4917
0
      )
4918
0
      .finish()
4919
0
    );
4920
0
  } else {
4921
0
    cb(kWPANTUNDStatus_InvalidArgument);
4922
0
  }
4923
0
}
4924
4925
void
4926
SpinelNCPInstance::insert_prop_MACDenylistEntries(const boost::any &value, CallbackWithStatus cb)
4927
0
{
4928
0
  Data ext_address = any_to_data(value);
4929
0
  int8_t rssi = kWPANTUND_Allowlist_RssiOverrideDisabled;
4930
4931
0
  if (ext_address.size() == sizeof(spinel_eui64_t)) {
4932
0
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
4933
0
      .set_callback(cb)
4934
0
      .add_command(
4935
0
        SpinelPackData(
4936
0
          SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(SPINEL_DATATYPE_EUI64_S SPINEL_DATATYPE_INT8_S),
4937
0
          SPINEL_PROP_MAC_DENYLIST,
4938
0
          ext_address.data(),
4939
0
          rssi
4940
0
        )
4941
0
      )
4942
0
      .finish()
4943
0
    );
4944
0
  } else {
4945
0
    cb(kWPANTUNDStatus_InvalidArgument);
4946
0
  }
4947
0
}
4948
4949
void
4950
SpinelNCPInstance::insert_prop_MACFilterEntries(const boost::any &value, CallbackWithStatus cb)
4951
0
{
4952
0
  Data ext_address = any_to_data(value);
4953
4954
0
  if (ext_address.size() == sizeof(spinel_eui64_t)) {
4955
0
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
4956
0
      .set_callback(cb)
4957
0
      .add_command(
4958
0
        SpinelPackData(
4959
0
          SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(SPINEL_DATATYPE_EUI64_S SPINEL_DATATYPE_INT8_S),
4960
0
          SPINEL_PROP_MAC_FIXED_RSS,
4961
0
          ext_address.data(),
4962
0
          mMacFilterFixedRssi
4963
0
        )
4964
0
      )
4965
0
      .finish()
4966
0
    );
4967
0
  } else {
4968
0
    cb(kWPANTUNDStatus_InvalidArgument);
4969
0
  }
4970
0
}
4971
4972
void
4973
SpinelNCPInstance::property_insert_value(const std::string &key, const boost::any &value, CallbackWithStatus cb)
4974
0
{
4975
0
  syslog(LOG_INFO, "property_insert_value: key: \"%s\"", key.c_str());
4976
4977
0
  if (!mEnabled) {
4978
0
    cb(kWPANTUNDStatus_InvalidWhenDisabled);
4979
0
    return;
4980
0
  }
4981
4982
0
  try {
4983
0
    if (mVendorCustom.is_property_key_supported(key)) {
4984
0
      mVendorCustom.property_insert_value(key, value, cb);
4985
4986
0
    } else {
4987
0
      NCPInstanceBase::property_insert_value(key, value, cb);
4988
0
    }
4989
0
  } catch (const boost::bad_any_cast &x) {
4990
    // We will get a bad_any_cast exception if the property is of
4991
    // the wrong type.
4992
0
    syslog(LOG_ERR,"property_insert_value: Bad type for property \"%s\" (%s)", key.c_str(), x.what());
4993
0
    cb(kWPANTUNDStatus_InvalidArgument);
4994
0
  } catch (const std::invalid_argument &x) {
4995
    // We will get a bad_any_cast exception if the property is of
4996
    // the wrong type.
4997
0
    syslog(LOG_ERR,"property_insert_value: Invalid argument for property \"%s\" (%s)", key.c_str(), x.what());
4998
0
    cb(kWPANTUNDStatus_InvalidArgument);
4999
0
  }
5000
0
}
5001
5002
// ----------------------------------------------------------------------------
5003
// Property Remove Handlers
5004
5005
void
5006
SpinelNCPInstance::register_remove_handler(const char *prop_name, PropUpdateHandler handler)
5007
41.8k
{
5008
41.8k
  NCPInstanceBase::register_prop_remove_handler(prop_name, handler);
5009
41.8k
}
5010
5011
void
5012
SpinelNCPInstance::register_remove_handler_capability(const char *prop_name, unsigned int capability,
5013
  PropUpdateHandler handler)
5014
41.8k
{
5015
41.8k
  register_remove_handler(
5016
41.8k
    prop_name,
5017
41.8k
    boost::bind(&SpinelNCPInstance::check_capability_prop_update, this, _1, _2, _3, capability, handler));
5018
41.8k
}
5019
5020
void
5021
SpinelNCPInstance::regsiter_all_remove_handlers(void)
5022
13.9k
{
5023
13.9k
  register_remove_handler_capability(
5024
13.9k
    kWPANTUNDProperty_MACAllowlistEntries,
5025
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
5026
13.9k
    boost::bind(&SpinelNCPInstance::remove_prop_MACAllowlistEntries, this, _1, _2));
5027
13.9k
  register_remove_handler_capability(
5028
13.9k
    kWPANTUNDProperty_MACDenylistEntries,
5029
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
5030
13.9k
    boost::bind(&SpinelNCPInstance::remove_prop_MACDenylistEntries, this, _1, _2));
5031
13.9k
  register_remove_handler_capability(
5032
13.9k
    kWPANTUNDProperty_MACFilterEntries,
5033
13.9k
    SPINEL_CAP_MAC_ALLOWLIST,
5034
13.9k
    boost::bind(&SpinelNCPInstance::remove_prop_MACFilterEntries, this, _1, _2));
5035
13.9k
}
5036
5037
void
5038
SpinelNCPInstance::remove_prop_MACAllowlistEntries(const boost::any &value, CallbackWithStatus cb)
5039
0
{
5040
0
  Data ext_address = any_to_data(value);
5041
5042
0
  if (ext_address.size() == sizeof(spinel_eui64_t)) {
5043
0
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
5044
0
      .set_callback(cb)
5045
0
      .add_command(
5046
0
        SpinelPackData(
5047
0
          SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(SPINEL_DATATYPE_EUI64_S),
5048
0
          SPINEL_PROP_MAC_ALLOWLIST,
5049
0
          ext_address.data()
5050
0
        )
5051
0
      )
5052
0
      .finish()
5053
0
    );
5054
0
  } else {
5055
0
    cb(kWPANTUNDStatus_InvalidArgument);
5056
0
  }
5057
0
}
5058
5059
void
5060
SpinelNCPInstance::remove_prop_MACDenylistEntries(const boost::any &value, CallbackWithStatus cb)
5061
0
{
5062
0
  Data ext_address = any_to_data(value);
5063
5064
0
  if (ext_address.size() == sizeof(spinel_eui64_t)) {
5065
0
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
5066
0
      .set_callback(cb)
5067
0
      .add_command(
5068
0
        SpinelPackData(
5069
0
          SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(SPINEL_DATATYPE_EUI64_S),
5070
0
          SPINEL_PROP_MAC_DENYLIST,
5071
0
          ext_address.data()
5072
0
        )
5073
0
      )
5074
0
      .finish()
5075
0
    );
5076
0
  } else {
5077
0
    cb(kWPANTUNDStatus_InvalidArgument);
5078
0
  }
5079
0
}
5080
5081
void
5082
SpinelNCPInstance::remove_prop_MACFilterEntries(const boost::any &value, CallbackWithStatus cb)
5083
0
{
5084
0
  Data ext_address = any_to_data(value);
5085
5086
0
  if (ext_address.size() == sizeof(spinel_eui64_t)) {
5087
0
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
5088
0
      .set_callback(cb)
5089
0
      .add_command(
5090
0
        SpinelPackData(
5091
0
          SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(SPINEL_DATATYPE_EUI64_S),
5092
0
          SPINEL_PROP_MAC_FIXED_RSS,
5093
0
          ext_address.data()
5094
0
        )
5095
0
      )
5096
0
      .finish()
5097
0
    );
5098
0
  } else {
5099
0
    cb(kWPANTUNDStatus_InvalidArgument);
5100
0
  }
5101
0
}
5102
5103
void
5104
SpinelNCPInstance::property_remove_value(const std::string &key, const boost::any &value, CallbackWithStatus cb)
5105
0
{
5106
0
  syslog(LOG_INFO, "property_remove_value: key: \"%s\"", key.c_str());
5107
5108
0
  try {
5109
0
    if (mVendorCustom.is_property_key_supported(key)) {
5110
0
      mVendorCustom.property_remove_value(key, value, cb);
5111
5112
0
    } else {
5113
0
      NCPInstanceBase::property_remove_value(key, value, cb);
5114
0
    }
5115
5116
0
  } catch (const boost::bad_any_cast &x) {
5117
    // We will get a bad_any_cast exception if the property is of
5118
    // the wrong type.
5119
0
    syslog(LOG_ERR,"property_remove_value: Bad type for property \"%s\" (%s)", key.c_str(), x.what());
5120
0
    cb(kWPANTUNDStatus_InvalidArgument);
5121
0
  } catch (const std::invalid_argument &x) {
5122
    // We will get a bad_any_cast exception if the property is of
5123
    // the wrong type.
5124
0
    syslog(LOG_ERR,"property_remove_value: Invalid argument for property \"%s\" (%s)", key.c_str(), x.what());
5125
0
    cb(kWPANTUNDStatus_InvalidArgument);
5126
0
  }
5127
0
}
5128
5129
void
5130
SpinelNCPInstance::reset_tasks(wpantund_status_t status)
5131
1.90k
{
5132
1.90k
  NCPInstanceBase::reset_tasks(status);
5133
4.49k
  while(!mTaskQueue.empty()) {
5134
2.58k
    mTaskQueue.front()->finish(status);
5135
2.58k
    mTaskQueue.pop_front();
5136
2.58k
  }
5137
1.90k
}
5138
5139
void
5140
SpinelNCPInstance::handle_ncp_spinel_value_is_ON_MESH_NETS(const uint8_t *value_data_ptr, spinel_size_t value_data_len)
5141
12.9k
{
5142
12.9k
  std::multimap<IPv6Prefix, OnMeshPrefixEntry>::iterator iter;
5143
12.9k
  std::multimap<IPv6Prefix, OnMeshPrefixEntry> on_mesh_prefixes(mOnMeshPrefixes);
5144
12.9k
  int num_prefix = 0;
5145
5146
28.7k
  while (value_data_len > 0) {
5147
23.3k
    spinel_ssize_t len = 0;
5148
23.3k
    struct in6_addr *prefix_addr = NULL;
5149
23.3k
    uint8_t prefix_len = 0;
5150
23.3k
    bool stable = false;
5151
23.3k
    uint8_t flags = 0;
5152
23.3k
    uint8_t flags_extended = 0;
5153
23.3k
    uint16_t mesh_nets_flags = 0;
5154
23.3k
    bool is_local = false;
5155
23.3k
    uint16_t rloc16 = 0;
5156
5157
23.3k
    len = spinel_datatype_unpack(
5158
23.3k
      value_data_ptr,
5159
23.3k
      value_data_len,
5160
23.3k
      SPINEL_DATATYPE_STRUCT_S(
5161
23.3k
        SPINEL_DATATYPE_IPv6ADDR_S // Prefix
5162
23.3k
        SPINEL_DATATYPE_UINT8_S    // Prefix length (in bits)
5163
23.3k
        SPINEL_DATATYPE_BOOL_S     // stable
5164
23.3k
        SPINEL_DATATYPE_UINT8_S    // flags
5165
23.3k
        SPINEL_DATATYPE_BOOL_S     // is_local
5166
23.3k
        SPINEL_DATATYPE_UINT16_S   // RLOC16
5167
23.3k
        SPINEL_DATATYPE_UINT8_S    // flags extended
5168
23.3k
      ),
5169
23.3k
      &prefix_addr,
5170
23.3k
      &prefix_len,
5171
23.3k
      &stable,
5172
23.3k
      &flags,
5173
23.3k
      &is_local,
5174
23.3k
      &rloc16,
5175
23.3k
      &flags_extended
5176
23.3k
    );
5177
5178
23.3k
    if (len <= 0) {
5179
7.49k
      break;
5180
7.49k
    }
5181
5182
15.8k
    mesh_nets_flags = (flags_extended << 8) | flags;
5183
5184
15.8k
    syslog(
5185
15.8k
      LOG_INFO,
5186
15.8k
      "[-NCP-]: On-mesh net [%d] \"%s/%d\" stable:%s local:%s flags:%s, rloc16:0x%04x",
5187
15.8k
      num_prefix,
5188
15.8k
      in6_addr_to_string(*prefix_addr).c_str(),
5189
15.8k
      prefix_len,
5190
15.8k
      stable ? "yes" : "no",
5191
15.8k
      is_local ? "yes" : "no",
5192
15.8k
      on_mesh_prefix_flags_to_string(mesh_nets_flags).c_str(),
5193
15.8k
      rloc16
5194
15.8k
    );
5195
5196
15.8k
    num_prefix++;
5197
5198
15.8k
    if (!is_local) {
5199
5200
      // Go through the `on_mesh_prefixes` list (which is the copy of mOnMeshPrefixes)
5201
      // and check if this entry is already on the list, if so remove it.
5202
5203
15.1k
      IPv6Prefix prefix(*prefix_addr, prefix_len);
5204
15.1k
      OnMeshPrefixEntry entry(kOriginThreadNCP, mesh_nets_flags, stable, rloc16);
5205
5206
15.1k
      iter = on_mesh_prefixes.lower_bound(prefix);
5207
5208
15.1k
      if (iter != on_mesh_prefixes.end()) {
5209
5.38k
        std::multimap<IPv6Prefix, OnMeshPrefixEntry>::iterator upper_iter = on_mesh_prefixes.upper_bound(prefix);
5210
5211
11.8k
        for (; iter != upper_iter; ++iter) {
5212
7.14k
          if (iter->second == entry) {
5213
685
            on_mesh_prefixes.erase(iter);
5214
685
            break;
5215
685
          }
5216
7.14k
        }
5217
5.38k
      }
5218
5219
15.1k
      on_mesh_prefix_was_added(kOriginThreadNCP, *prefix_addr, prefix_len, mesh_nets_flags, stable, rloc16);
5220
15.1k
    }
5221
5222
15.8k
    value_data_ptr += len;
5223
15.8k
    value_data_len -= len;
5224
15.8k
  }
5225
5226
  // Since this was the whole list, we need to remove any prefixes
5227
  // which originated from NCP that that weren't in the new list.
5228
5229
23.2k
  for (iter = on_mesh_prefixes.begin(); iter != on_mesh_prefixes.end(); ++iter) {
5230
10.2k
    if (iter->second.is_from_ncp()) {
5231
10.2k
      on_mesh_prefix_was_removed(
5232
10.2k
        kOriginThreadNCP,
5233
10.2k
        iter->first.get_prefix(),
5234
10.2k
        iter->first.get_length(),
5235
10.2k
        iter->second.get_flags(),
5236
10.2k
        iter->second.is_stable(),
5237
10.2k
        iter->second.get_rloc()
5238
10.2k
      );
5239
10.2k
    }
5240
10.2k
  }
5241
12.9k
}
5242
5243
void
5244
SpinelNCPInstance::handle_ncp_spinel_value_is_OFF_MESH_ROUTES(const uint8_t* value_data_ptr, spinel_size_t value_data_len)
5245
3.21k
{
5246
3.21k
  std::multimap<IPv6Prefix, OffMeshRouteEntry>::iterator iter;
5247
3.21k
  std::multimap<IPv6Prefix, OffMeshRouteEntry> off_mesh_routes(mOffMeshRoutes);
5248
3.21k
  int num_routes = 0;
5249
5250
8.83k
  while (value_data_len > 0) {
5251
7.20k
    spinel_ssize_t len;
5252
7.20k
    struct in6_addr *route_prefix = NULL;
5253
7.20k
    uint8_t prefix_len;
5254
7.20k
    bool is_stable;
5255
7.20k
    uint8_t flags;
5256
7.20k
    bool is_local;
5257
7.20k
    bool next_hop_is_this_device;
5258
7.20k
    uint16_t rloc16;
5259
7.20k
    RoutePreference preference;
5260
5261
7.20k
    len = spinel_datatype_unpack(
5262
7.20k
      value_data_ptr,
5263
7.20k
      value_data_len,
5264
7.20k
      SPINEL_DATATYPE_STRUCT_S(
5265
7.20k
        SPINEL_DATATYPE_IPv6ADDR_S      // Route Prefix
5266
7.20k
        SPINEL_DATATYPE_UINT8_S         // Prefix Length (in bits)
5267
7.20k
        SPINEL_DATATYPE_BOOL_S          // isStable
5268
7.20k
        SPINEL_DATATYPE_UINT8_S         // Flags
5269
7.20k
        SPINEL_DATATYPE_BOOL_S          // IsLocal
5270
7.20k
        SPINEL_DATATYPE_BOOL_S          // NextHopIsThisDevice
5271
7.20k
        SPINEL_DATATYPE_UINT16_S        // RLOC16
5272
7.20k
      ),
5273
7.20k
      &route_prefix,
5274
7.20k
      &prefix_len,
5275
7.20k
      &is_stable,
5276
7.20k
      &flags,
5277
7.20k
      &is_local,
5278
7.20k
      &next_hop_is_this_device,
5279
7.20k
      &rloc16
5280
7.20k
    );
5281
5282
7.20k
    if (len <= 0) {
5283
1.57k
      break;
5284
1.57k
    }
5285
5286
5.62k
    preference = convert_flags_to_route_preference(flags);
5287
5288
5.62k
    syslog(LOG_INFO, "[-NCP-]: Off-mesh route [%d] \"%s/%d\" stable:%s local:%s preference:%s, next_hop_is_this_device:%s, rloc16:0x%0x",
5289
5.62k
      num_routes, in6_addr_to_string(*route_prefix).c_str(), prefix_len, is_stable ? "yes" : "no",
5290
5.62k
      is_local ? "yes" : "no", NCPControlInterface::external_route_priority_to_string(preference).c_str(),
5291
5.62k
      next_hop_is_this_device ? "yes" : "no", rloc16);
5292
5293
5.62k
    num_routes++;
5294
5295
5.62k
    if (!is_local) {
5296
5297
      // Go through the `off_mesh_routes` list (which is the copy of mOffMeshRoutes)
5298
      // and check if this entry is already on the list, if so remove it.
5299
5300
5.38k
      IPv6Prefix route(*route_prefix, prefix_len);
5301
5.38k
      OffMeshRouteEntry entry(kOriginThreadNCP, preference, is_stable, rloc16, next_hop_is_this_device);
5302
5.38k
      iter = off_mesh_routes.lower_bound(route);
5303
5304
5.38k
      if (iter != off_mesh_routes.end()) {
5305
2.45k
        std::multimap<IPv6Prefix, OffMeshRouteEntry>::iterator upper_iter = off_mesh_routes.upper_bound(route);
5306
5307
5.51k
        for (; iter != upper_iter; ++iter) {
5308
3.64k
          if (iter->second == entry) {
5309
581
            off_mesh_routes.erase(iter);
5310
581
            break;
5311
581
          }
5312
3.64k
        }
5313
2.45k
      }
5314
5315
5.38k
      route_was_added(kOriginThreadNCP, *route_prefix, prefix_len, preference, is_stable, rloc16,
5316
5.38k
        next_hop_is_this_device);
5317
5.38k
    }
5318
5319
5.62k
    value_data_ptr += len;
5320
5.62k
    value_data_len -= len;
5321
5.62k
  }
5322
5323
  // Since this was the whole list, we need to remove any routes
5324
  // which originated from NCP that that weren't in the new list.
5325
5326
5.98k
  for (iter = off_mesh_routes.begin(); iter != off_mesh_routes.end(); ++iter) {
5327
2.77k
    if (iter->second.is_from_ncp()) {
5328
2.77k
      route_was_removed(kOriginThreadNCP, iter->first.get_prefix(), iter->first.get_length(),
5329
2.77k
        iter->second.get_preference(), iter->second.is_stable(), iter->second.get_rloc());
5330
2.77k
    }
5331
2.77k
  }
5332
3.21k
}
5333
5334
void
5335
SpinelNCPInstance::handle_ncp_spinel_value_is_SERVICES(const uint8_t* value_data_ptr, spinel_size_t value_data_len)
5336
2.08k
{
5337
2.08k
  uint32_t enterprise_number;
5338
2.08k
  const uint8_t *service_data_ptr = NULL;
5339
2.08k
  spinel_size_t service_data_len = 0;
5340
2.08k
  bool stable = false;
5341
2.08k
  const uint8_t *server_data_ptr = NULL;
5342
2.08k
  spinel_size_t server_data_len = 0;
5343
2.08k
  uint16_t rloc16;
5344
2.08k
  int num_services = 0;
5345
2.08k
  spinel_ssize_t len;
5346
5347
2.08k
  std::vector<ServiceEntry> entries(mServiceEntries);
5348
2.08k
  std::vector<ServiceEntry>::iterator iter;
5349
5350
7.63k
  while (value_data_len > 0) {
5351
6.64k
    len = spinel_datatype_unpack(
5352
6.64k
      value_data_ptr,
5353
6.64k
      value_data_len,
5354
6.64k
      SPINEL_DATATYPE_STRUCT_S(
5355
6.64k
        SPINEL_DATATYPE_UINT32_S    // Enterprise Number
5356
6.64k
        SPINEL_DATATYPE_DATA_WLEN_S // Service Data
5357
6.64k
        SPINEL_DATATYPE_BOOL_S      // stable
5358
6.64k
        SPINEL_DATATYPE_DATA_WLEN_S // Server Data
5359
6.64k
        SPINEL_DATATYPE_UINT16_S    // RLOC
5360
6.64k
      ),
5361
6.64k
      &enterprise_number,
5362
6.64k
      &service_data_ptr,
5363
6.64k
      &service_data_len,
5364
6.64k
      &stable,
5365
6.64k
      &server_data_ptr,
5366
6.64k
      &server_data_len,
5367
6.64k
      &rloc16
5368
6.64k
    );
5369
5370
6.64k
    if (len <= 0) {
5371
1.09k
      break;
5372
1.09k
    }
5373
5374
5.55k
    syslog(LOG_INFO, "[-NCP-]: Service [%d] enterprise_number:%u stable:%s RLOC16:%04x",
5375
5.55k
      num_services, enterprise_number, stable ? "yes" : "no", rloc16);
5376
5377
5.55k
    Data service_data(service_data_ptr, service_data_len);
5378
5.55k
    Data server_data(server_data_ptr, server_data_len);
5379
5380
5.55k
    ServiceEntry entry(kOriginThreadNCP, enterprise_number, service_data, stable, server_data);
5381
5382
5.55k
    iter = std::find(entries.begin(), entries.end(), entry);
5383
5.55k
    if (iter != entries.end()) {
5384
1.33k
      entries.erase(iter);
5385
1.33k
    }
5386
5387
5.55k
    service_was_added(kOriginThreadNCP, enterprise_number, service_data, stable, server_data);
5388
5389
5.55k
    value_data_ptr += len;
5390
5.55k
    value_data_len -= len;
5391
5.55k
    num_services += 1;
5392
5.55k
  }
5393
5394
4.36k
  for (iter = entries.begin(); iter != entries.end(); ++iter) {
5395
2.28k
    if (iter->is_from_ncp()) {
5396
2.28k
      service_was_removed(kOriginThreadNCP, iter->get_enterprise_number(), iter->get_service_data());
5397
2.28k
    }
5398
2.28k
  }
5399
2.08k
}
5400
5401
void
5402
SpinelNCPInstance::handle_ncp_spinel_value_is(spinel_prop_key_t key, const uint8_t* value_data_ptr, spinel_size_t value_data_len)
5403
126k
{
5404
126k
  const uint8_t *original_value_data_ptr = value_data_ptr;
5405
126k
  spinel_size_t original_value_data_len = value_data_len;
5406
5407
126k
  if (key == SPINEL_PROP_LAST_STATUS) {
5408
12.6k
    spinel_status_t status = SPINEL_STATUS_OK;
5409
12.6k
    spinel_datatype_unpack(value_data_ptr, value_data_len, "i", &status);
5410
12.6k
    syslog(LOG_INFO, "[-NCP-]: Last status (%s, %d)", spinel_status_to_cstr(status), status);
5411
12.6k
    if ((status >= SPINEL_STATUS_RESET__BEGIN) && (status <= SPINEL_STATUS_RESET__END)) {
5412
3.04k
      syslog(LOG_NOTICE, "[-NCP-]: NCP was reset (%s, %d)", spinel_status_to_cstr(status), status);
5413
3.04k
      process_event(EVENT_NCP_RESET, status);
5414
3.04k
      if (!mResetIsExpected && (mDriverState == NORMAL_OPERATION)) {
5415
34
        wpantund_status_t wstatus = kWPANTUNDStatus_NCP_Reset;
5416
34
        switch(status) {
5417
3
        case SPINEL_STATUS_RESET_CRASH:
5418
3
        case SPINEL_STATUS_RESET_FAULT:
5419
4
        case SPINEL_STATUS_RESET_ASSERT:
5420
6
        case SPINEL_STATUS_RESET_WATCHDOG:
5421
7
        case SPINEL_STATUS_RESET_OTHER:
5422
7
          wstatus = kWPANTUNDStatus_NCP_Crashed;
5423
7
          break;
5424
27
        default:
5425
27
          break;
5426
34
        }
5427
34
        reset_tasks(wstatus);
5428
34
      }
5429
5430
3.04k
      if (mDriverState == NORMAL_OPERATION) {
5431
34
        reinitialize_ncp();
5432
34
      }
5433
3.04k
      mResetIsExpected = false;
5434
3.04k
      return;
5435
9.57k
    } else if ((status >= SPINEL_STATUS_JOIN__BEGIN) && (status <= SPINEL_STATUS_JOIN__END)) {
5436
4.69k
      if (status == SPINEL_STATUS_JOIN_SUCCESS) {
5437
343
        change_ncp_state(COMMISSIONED);
5438
343
      }
5439
4.34k
      else {
5440
4.34k
        change_ncp_state(CREDENTIALS_NEEDED);
5441
4.34k
      }
5442
4.88k
    } else if (status == SPINEL_STATUS_INVALID_COMMAND) {
5443
88
      syslog(LOG_NOTICE, "[-NCP-]: COMMAND NOT RECOGNIZED");
5444
88
    }
5445
114k
  } else if (key == SPINEL_PROP_NCP_VERSION) {
5446
1.32k
    const char* ncp_version = NULL;
5447
1.32k
    spinel_ssize_t len = spinel_datatype_unpack(value_data_ptr, value_data_len, "U", &ncp_version);
5448
1.32k
    if ((len <= 0) || (ncp_version == NULL)) {
5449
11
      syslog(LOG_CRIT, "[-NCP-]: Got a corrupted NCP version");
5450
      // TODO: Properly handle NCP Misbehavior
5451
11
      change_ncp_state(FAULT);
5452
1.31k
    } else {
5453
1.31k
      set_ncp_version_string(ncp_version);
5454
1.31k
    }
5455
5456
112k
  } else if (key == SPINEL_PROP_INTERFACE_TYPE) {
5457
117
    unsigned int interface_type = 0;
5458
117
    spinel_datatype_unpack(value_data_ptr, value_data_len, "i", &interface_type);
5459
5460
117
    if (interface_type != SPINEL_PROTOCOL_TYPE_THREAD) {
5461
31
      syslog(LOG_CRIT, "[-NCP-]: NCP is using unsupported protocol type (%d)", interface_type);
5462
31
      change_ncp_state(FAULT);
5463
31
    }
5464
5465
112k
  } else if (key == SPINEL_PROP_PROTOCOL_VERSION) {
5466
461
    unsigned int protocol_version_major = 0;
5467
461
    unsigned int protocol_version_minor = 0;
5468
461
    spinel_datatype_unpack(value_data_ptr, value_data_len, "ii", &protocol_version_major, &protocol_version_minor);
5469
5470
461
    if (protocol_version_major != SPINEL_PROTOCOL_VERSION_THREAD_MAJOR) {
5471
113
      syslog(LOG_CRIT, "[-NCP-]: NCP is using unsupported protocol version (NCP:%d, wpantund:%d)", protocol_version_major, SPINEL_PROTOCOL_VERSION_THREAD_MAJOR);
5472
113
      change_ncp_state(FAULT);
5473
113
    }
5474
5475
461
    if (protocol_version_minor != SPINEL_PROTOCOL_VERSION_THREAD_MINOR) {
5476
281
      syslog(LOG_WARNING, "[-NCP-]: NCP is using different protocol minor version (NCP:%d, wpantund:%d)", protocol_version_minor, SPINEL_PROTOCOL_VERSION_THREAD_MINOR);
5477
281
    }
5478
5479
112k
  } else if (key == SPINEL_PROP_CAPS) {
5480
3.09k
    const uint8_t* data_ptr = value_data_ptr;
5481
3.09k
    spinel_size_t data_len = value_data_len;
5482
3.09k
    std::set<unsigned int> capabilities;
5483
5484
32.6k
    while(data_len != 0) {
5485
29.8k
      unsigned int value = 0;
5486
29.8k
      spinel_ssize_t parse_len = spinel_datatype_unpack(data_ptr, data_len, SPINEL_DATATYPE_UINT_PACKED_S, &value);
5487
29.8k
      if (parse_len <= 0) {
5488
332
        syslog(LOG_WARNING, "[-NCP-]: Capability Parse failure");
5489
332
        break;
5490
332
      }
5491
29.5k
      capabilities.insert(value);
5492
29.5k
      syslog(LOG_INFO, "[-NCP-]: Capability (%s, %d)", spinel_capability_to_cstr(value), value);
5493
5494
29.5k
      data_ptr += parse_len;
5495
29.5k
      data_len -= parse_len;
5496
29.5k
    }
5497
5498
3.09k
    if (capabilities != mCapabilities) {
5499
1.94k
      mCapabilities = capabilities;
5500
1.94k
    }
5501
5502
109k
  } else if (key == SPINEL_PROP_NET_NETWORK_NAME) {
5503
1.36k
    const char* value = NULL;
5504
1.36k
    spinel_ssize_t len = spinel_datatype_unpack(value_data_ptr, value_data_len, "U", &value);
5505
5506
1.36k
    if ((len <= 0) || (value == NULL)) {
5507
3
      syslog(LOG_CRIT, "[-NCP-]: Got a corrupted NCP version");
5508
      // TODO: Properly handle NCP Misbehavior
5509
3
      change_ncp_state(FAULT);
5510
1.36k
    } else {
5511
1.36k
      syslog(LOG_INFO, "[-NCP-]: Network name \"%s\"", value);
5512
1.36k
      if (mCurrentNetworkInstance.name != value) {
5513
763
        mCurrentNetworkInstance.name = value;
5514
763
        signal_property_changed(kWPANTUNDProperty_NetworkName, mCurrentNetworkInstance.name);
5515
763
      }
5516
1.36k
    }
5517
5518
107k
  } else if (key == SPINEL_PROP_MCU_POWER_STATE) {
5519
7.07k
    uint8_t power_state = 0;
5520
7.07k
    spinel_ssize_t len = 0;
5521
5522
7.07k
    len  = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT8_S, &power_state);
5523
5524
7.07k
    if (len > 0) {
5525
6.99k
      syslog(LOG_INFO, "[-NCP-]: MCU power state \"%s\" (%d)",
5526
6.99k
        spinel_mcu_power_state_to_cstr(static_cast<spinel_mcu_power_state_t>(power_state)), power_state);
5527
5528
6.99k
      switch (get_ncp_state()) {
5529
4.19k
      case OFFLINE:
5530
5.51k
      case COMMISSIONED:
5531
5.51k
        if (power_state == SPINEL_MCU_POWER_STATE_LOW_POWER) {
5532
5.36k
          change_ncp_state(DEEP_SLEEP);
5533
5.36k
        }
5534
5.51k
        break;
5535
5536
887
      case DEEP_SLEEP:
5537
887
        if (power_state == SPINEL_MCU_POWER_STATE_ON) {
5538
549
          change_ncp_state(mIsCommissioned ? COMMISSIONED : OFFLINE);
5539
549
        }
5540
887
        break;
5541
5542
590
      default:
5543
590
        break;
5544
6.99k
      }
5545
6.99k
    }
5546
5547
100k
  } else if (key == SPINEL_PROP_IPV6_LL_ADDR) {
5548
439
    struct in6_addr *addr = NULL;
5549
5550
439
    spinel_datatype_unpack(value_data_ptr, value_data_len, "6", &addr);
5551
439
    if (addr != NULL) {
5552
322
      syslog(LOG_INFO, "[-NCP-]: Link-local IPv6 address \"%s\"", in6_addr_to_string(*addr).c_str());
5553
322
    }
5554
439
    update_link_local_address(addr);
5555
5556
100k
  } else if (key == SPINEL_PROP_IPV6_ML_ADDR) {
5557
1.15k
    struct in6_addr *addr = NULL;
5558
1.15k
    spinel_datatype_unpack(value_data_ptr, value_data_len, "6", &addr);
5559
1.15k
    if (addr != NULL) {
5560
984
      syslog(LOG_INFO, "[-NCP-]: Mesh-local IPv6 address \"%s\"", in6_addr_to_string(*addr).c_str());
5561
984
    }
5562
1.15k
    update_mesh_local_address(addr);
5563
5564
99.1k
  } else if (key == SPINEL_PROP_IPV6_ML_PREFIX) {
5565
663
    struct in6_addr *addr = NULL;
5566
663
    spinel_datatype_unpack(value_data_ptr, value_data_len, "6", &addr);
5567
663
    if (addr != NULL) {
5568
390
      syslog(LOG_INFO, "[-NCP-]: Mesh-local prefix \"%s\"", (in6_addr_to_string(*addr) + "/64").c_str());
5569
390
    }
5570
663
    update_mesh_local_prefix(addr);
5571
5572
98.4k
  } else if (key == SPINEL_PROP_IPV6_ADDRESS_TABLE) {
5573
2.27k
    std::map<struct in6_addr, UnicastAddressEntry>::const_iterator iter;
5574
2.27k
    std::map<struct in6_addr, UnicastAddressEntry> unicast_addresses(mUnicastAddresses);
5575
2.27k
    const struct in6_addr *addr = NULL;
5576
2.27k
    int num_address = 0;
5577
5578
9.19k
    while (value_data_len > 0) {
5579
8.29k
      const uint8_t *entry_ptr = NULL;
5580
8.29k
      spinel_size_t entry_len = 0;
5581
8.29k
      spinel_ssize_t len = 0;
5582
8.29k
      len = spinel_datatype_unpack(value_data_ptr, value_data_len, "D.", &entry_ptr, &entry_len);
5583
8.29k
      if (len < 1) {
5584
1.37k
        break;
5585
1.37k
      }
5586
5587
6.92k
      addr = reinterpret_cast<const struct in6_addr*>(entry_ptr);
5588
6.92k
      syslog(LOG_INFO, "[-NCP-]: IPv6 address [%d] \"%s\"", num_address, in6_addr_to_string(*addr).c_str());
5589
6.92k
      num_address++;
5590
6.92k
      unicast_addresses.erase(*addr);
5591
6.92k
      handle_ncp_spinel_value_inserted(key, entry_ptr, entry_len);
5592
5593
6.92k
      value_data_ptr += len;
5594
6.92k
      value_data_len -= len;
5595
6.92k
    }
5596
5597
2.27k
    syslog(LOG_INFO, "[-NCP-]: IPv6 address: Total %d address%s", num_address, (num_address > 1) ? "es" : "");
5598
5599
    // Since this was the whole list, we need to remove the addresses
5600
    // which originated from NCP that that weren't in the list.
5601
4.10k
    for (iter = unicast_addresses.begin(); iter != unicast_addresses.end(); ++iter) {
5602
1.83k
      if (iter->second.is_from_ncp()) {
5603
1.83k
        unicast_address_was_removed(kOriginThreadNCP, iter->first);
5604
1.83k
      }
5605
1.83k
    }
5606
5607
96.1k
  } else if (key == SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE) {
5608
3.30k
    std::map<struct in6_addr, MulticastAddressEntry>::const_iterator iter;
5609
3.30k
    std::map<struct in6_addr, MulticastAddressEntry> multicast_addresses(mMulticastAddresses);
5610
3.30k
    const struct in6_addr *addr = NULL;
5611
3.30k
    int num_address = 0;
5612
5613
10.1k
    while (value_data_len > 0) {
5614
8.18k
      const uint8_t *entry_ptr = NULL;
5615
8.18k
      spinel_size_t entry_len = 0;
5616
8.18k
      spinel_ssize_t len = 0;
5617
8.18k
      len = spinel_datatype_unpack(value_data_ptr, value_data_len, "D.", &entry_ptr, &entry_len);
5618
8.18k
      if (len < 1) {
5619
1.38k
        break;
5620
1.38k
      }
5621
5622
6.80k
      addr = reinterpret_cast<const struct in6_addr*>(entry_ptr);
5623
6.80k
      syslog(LOG_INFO, "[-NCP-]: Multicast IPv6 address [%d] \"%s\"", num_address, in6_addr_to_string(*addr).c_str());
5624
6.80k
      num_address++;
5625
6.80k
      multicast_addresses.erase(*addr);
5626
6.80k
      handle_ncp_spinel_value_inserted(key, entry_ptr, entry_len);
5627
5628
6.80k
      value_data_ptr += len;
5629
6.80k
      value_data_len -= len;
5630
6.80k
    }
5631
5632
    // Since this was the whole list, we need to remove the addresses
5633
    // which originated from NCP that that weren't in the list.
5634
6.38k
    for (iter = multicast_addresses.begin(); iter != multicast_addresses.end(); ++iter) {
5635
3.08k
      if (iter->second.is_from_ncp()) {
5636
3.08k
        multicast_address_was_left(kOriginThreadNCP, iter->first);
5637
3.08k
      }
5638
3.08k
    }
5639
5640
92.8k
  } else if (key == SPINEL_PROP_HWADDR) {
5641
650
    nl::Data hwaddr(value_data_ptr, value_data_len);
5642
650
    if (value_data_len == sizeof(mMACHardwareAddress)) {
5643
236
      set_mac_hardware_address(value_data_ptr);
5644
236
    }
5645
5646
92.2k
  } else if (key == SPINEL_PROP_MAC_15_4_LADDR) {
5647
1.06k
    nl::Data hwaddr(value_data_ptr, value_data_len);
5648
1.06k
    if (value_data_len == sizeof(mMACAddress)) {
5649
854
      set_mac_address(value_data_ptr);
5650
854
    }
5651
5652
91.1k
  } else if (key == SPINEL_PROP_MAC_15_4_PANID) {
5653
448
    uint16_t panid;
5654
448
    spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT16_S, &panid);
5655
448
    syslog(LOG_INFO, "[-NCP-]: PANID 0x%04X", panid);
5656
448
    if (panid != mCurrentNetworkInstance.panid) {
5657
212
      mCurrentNetworkInstance.panid = panid;
5658
212
      signal_property_changed(kWPANTUNDProperty_NetworkPANID, panid);
5659
212
    }
5660
5661
90.7k
  } else if (key == SPINEL_PROP_NET_XPANID) {
5662
936
    nl::Data xpanid(value_data_ptr, value_data_len);
5663
936
    char cstr_buf[200];
5664
936
    encode_data_into_string(value_data_ptr, value_data_len, cstr_buf, sizeof(cstr_buf), 0);
5665
936
    syslog(LOG_INFO, "[-NCP-] XPANID 0x%s", cstr_buf);
5666
5667
936
    if ((value_data_len == 8) && 0 != memcmp(xpanid.data(), mCurrentNetworkInstance.xpanid, 8)) {
5668
228
      memcpy(mCurrentNetworkInstance.xpanid, xpanid.data(), 8);
5669
228
      signal_property_changed(kWPANTUNDProperty_NetworkXPANID, xpanid);
5670
228
    }
5671
5672
89.7k
  } else if (key == SPINEL_PROP_NET_PSKC) {
5673
1.03k
    nl::Data network_pskc(value_data_ptr, value_data_len);
5674
1.03k
    if (network_pskc != mNetworkPSKc) {
5675
783
      mNetworkPSKc = network_pskc;
5676
783
      signal_property_changed(kWPANTUNDProperty_NetworkPSKc, mNetworkPSKc);
5677
783
    }
5678
5679
88.7k
  } else if (key == SPINEL_PROP_NET_MASTER_KEY) {
5680
1.35k
    nl::Data network_key(value_data_ptr, value_data_len);
5681
1.35k
    if (ncp_state_is_joining_or_joined(get_ncp_state())) {
5682
1.09k
      if (network_key != mNetworkKey) {
5683
710
        mNetworkKey = network_key;
5684
710
        signal_property_changed(kWPANTUNDProperty_NetworkKey, mNetworkKey);
5685
710
      }
5686
1.09k
    }
5687
5688
87.3k
  } else if (key == SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER) {
5689
779
    uint32_t network_key_index = 0;
5690
779
    spinel_ssize_t ret;
5691
5692
779
    ret = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT32_S, &network_key_index);
5693
5694
779
    __ASSERT_MACROS_check(ret > 0);
5695
5696
779
    if ((ret > 0) && (network_key_index != mNetworkKeyIndex)) {
5697
419
      mNetworkKeyIndex = network_key_index;
5698
419
      signal_property_changed(kWPANTUNDProperty_NetworkKeyIndex, mNetworkKeyIndex);
5699
419
    }
5700
5701
86.6k
  } else if (key == SPINEL_PROP_PHY_CHAN) {
5702
863
    unsigned int value = 0;
5703
863
    spinel_ssize_t ret;
5704
5705
863
    ret = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT_PACKED_S, &value);
5706
5707
863
    __ASSERT_MACROS_check(ret > 0);
5708
5709
863
    if (ret > 0) {
5710
609
      syslog(LOG_INFO, "[-NCP-]: Channel %d", value);
5711
609
      if (value != mCurrentNetworkInstance.channel) {
5712
455
        mCurrentNetworkInstance.channel = value;
5713
455
        signal_property_changed(kWPANTUNDProperty_NCPChannel, mCurrentNetworkInstance.channel);
5714
455
      }
5715
609
    }
5716
5717
85.7k
  } else if (key == SPINEL_PROP_PHY_CHAN_SUPPORTED) {
5718
1.19k
    boost::any mask_value;
5719
1.19k
    int ret = unpack_channel_mask(value_data_ptr, value_data_len, mask_value);
5720
5721
1.19k
    if (ret == kWPANTUNDStatus_Ok) {
5722
996
      mSupportedChannelMask = any_to_int(mask_value);
5723
996
      syslog(LOG_INFO, "[-NCP-]: Supported Channel Mask 0x%x", mSupportedChannelMask);
5724
996
    }
5725
5726
84.5k
  } else if (key == SPINEL_PROP_PHY_CHAN_PREFERRED) {
5727
342
    boost::any mask_value;
5728
342
    int ret = unpack_channel_mask(value_data_ptr, value_data_len, mask_value);
5729
5730
342
    if (ret == kWPANTUNDStatus_Ok) {
5731
233
      mPreferredChannelMask = any_to_int(mask_value);
5732
233
      syslog(LOG_INFO, "[-NCP-]: Preferred Channel Mask 0x%x", mPreferredChannelMask);
5733
233
    }
5734
5735
84.2k
  } else if (key == SPINEL_PROP_PHY_TX_POWER) {
5736
750
    int8_t value = 0;
5737
750
    spinel_ssize_t ret;
5738
5739
750
    ret = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_INT8_S, &value);
5740
5741
750
    __ASSERT_MACROS_check(ret > 0);
5742
5743
750
    if (ret > 0) {
5744
531
      syslog(LOG_INFO, "[-NCP-]: Tx power %d", value);
5745
531
      if (value != mTXPower) {
5746
276
        mTXPower = value;
5747
276
        signal_property_changed(kWPANTUNDProperty_NCPTXPower, mTXPower);
5748
276
      }
5749
531
    }
5750
5751
83.4k
  } else if (key == SPINEL_PROP_STREAM_DEBUG) {
5752
454
    handle_ncp_debug_stream(value_data_ptr, value_data_len);
5753
5754
83.0k
  } else if (key == SPINEL_PROP_STREAM_LOG) {
5755
2.90k
    handle_ncp_log_stream(value_data_ptr, value_data_len);
5756
5757
80.1k
  } else if (key == SPINEL_PROP_NET_ROLE) {
5758
4.02k
    uint8_t value = 0;
5759
4.02k
    spinel_ssize_t ret;
5760
5761
4.02k
    ret = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT8_S, &value);
5762
5763
4.02k
    __ASSERT_MACROS_check(ret > 0);
5764
5765
4.02k
    if (ret > 0) {
5766
3.77k
      syslog(LOG_INFO, "[-NCP-]: Net Role \"%s\" (%d)", spinel_net_role_to_cstr(value), value);
5767
5768
3.77k
      if (ncp_state_is_joining_or_joined(get_ncp_state())
5769
2.42k
        && (value != SPINEL_NET_ROLE_DETACHED)
5770
1.96k
                          && (value != SPINEL_NET_ROLE_DISABLED)
5771
3.77k
      ) {
5772
1.58k
        change_ncp_state(ASSOCIATED);
5773
1.58k
      }
5774
5775
3.77k
      if (value == SPINEL_NET_ROLE_CHILD) {
5776
1.02k
        if ((mThreadMode & SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE) != 0) {
5777
210
          update_node_type(END_DEVICE);
5778
811
        } else {
5779
811
          update_node_type(SLEEPY_END_DEVICE);
5780
811
        }
5781
5782
2.75k
      } else if (value == SPINEL_NET_ROLE_ROUTER) {
5783
136
        update_node_type(ROUTER);
5784
5785
2.61k
      } else if (value == SPINEL_NET_ROLE_LEADER) {
5786
73
        update_node_type(LEADER);
5787
5788
2.54k
                        } else if (value == SPINEL_NET_ROLE_DETACHED || value == SPINEL_NET_ROLE_DISABLED) {
5789
1.18k
        update_node_type(UNKNOWN);
5790
1.18k
        if (ncp_state_is_associated(get_ncp_state())) {
5791
720
          change_ncp_state(ISOLATED);
5792
720
        }
5793
1.18k
      }
5794
3.77k
    }
5795
5796
76.0k
  } else if (key == SPINEL_PROP_THREAD_MODE) {
5797
3.23k
    uint8_t value = mThreadMode;
5798
3.23k
    spinel_ssize_t ret;
5799
5800
3.23k
    ret = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT8_S, &value);
5801
5802
3.23k
    __ASSERT_MACROS_check(ret > 0);
5803
5804
3.23k
    if (ret > 0) {
5805
2.85k
      syslog(LOG_INFO, "[-NCP-]: Thread Mode \"%s\" (0x%02x)", thread_mode_to_string(value).c_str(), value);
5806
2.85k
      mThreadMode = value;
5807
5808
2.85k
      switch (get_ncp_state())
5809
2.85k
      {
5810
651
      case ISOLATED:
5811
651
        if ((mThreadMode & SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE) != 0) {
5812
363
          change_ncp_state(ASSOCIATING);
5813
363
        }
5814
651
        break;
5815
5816
677
      case ASSOCIATING:
5817
677
        if (mIsCommissioned && ((mThreadMode & SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE) == 0)) {
5818
346
          change_ncp_state(ISOLATED);
5819
346
        }
5820
677
        break;
5821
5822
1.53k
      default:
5823
1.53k
        break;
5824
2.85k
      }
5825
5826
2.85k
      switch (mNodeType)
5827
2.85k
      {
5828
646
      case END_DEVICE:
5829
1.33k
      case SLEEPY_END_DEVICE:
5830
1.33k
        if ((mThreadMode & SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE) != 0) {
5831
656
          update_node_type(END_DEVICE);
5832
674
        } else {
5833
674
          update_node_type(SLEEPY_END_DEVICE);
5834
674
        }
5835
1.33k
        break;
5836
5837
1.52k
      default:
5838
1.52k
        break;
5839
2.85k
      }
5840
2.85k
    }
5841
5842
72.8k
  } else if (key == SPINEL_PROP_NET_SAVED) {
5843
7.45k
    bool is_commissioned = false;
5844
7.45k
    spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_BOOL_S, &is_commissioned);
5845
7.45k
    syslog(LOG_INFO, "[-NCP-]: NetSaved (NCP is commissioned?) \"%s\" ", is_commissioned ? "yes" : "no");
5846
7.45k
    mIsCommissioned = is_commissioned;
5847
7.45k
    if (mIsCommissioned && (get_ncp_state() == OFFLINE)) {
5848
3.05k
      change_ncp_state(COMMISSIONED);
5849
4.39k
    } else if (!mIsCommissioned && (get_ncp_state() == COMMISSIONED)) {
5850
2.91k
      change_ncp_state(OFFLINE);
5851
2.91k
    }
5852
5853
65.4k
  } else if (key == SPINEL_PROP_NET_STACK_UP) {
5854
11.6k
    bool is_stack_up = false;
5855
11.6k
    spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_BOOL_S, &is_stack_up);
5856
11.6k
    syslog(LOG_INFO, "[-NCP-]: Stack is %sup", is_stack_up ? "" : "not ");
5857
5858
11.6k
    if (is_stack_up) {
5859
3.24k
      if (!ncp_state_is_joining_or_joined(get_ncp_state())) {
5860
2.69k
        if (mIsCommissioned && ((mThreadMode & SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE) == 0)) {
5861
2.09k
          change_ncp_state(ISOLATED);
5862
2.09k
        } else {
5863
606
          change_ncp_state(ASSOCIATING);
5864
606
        }
5865
2.69k
      }
5866
8.43k
    } else {
5867
8.43k
      if (!ncp_state_is_joining(get_ncp_state())) {
5868
8.03k
        change_ncp_state(mIsCommissioned ? COMMISSIONED : OFFLINE);
5869
8.03k
      }
5870
8.43k
    }
5871
5872
53.7k
  } else if (key == SPINEL_PROP_NET_IF_UP) {
5873
3.34k
    bool is_if_up = false;
5874
3.34k
    spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_BOOL_S, &is_if_up);
5875
3.34k
    syslog(LOG_INFO, "[-NCP-]: Interface is %sup", is_if_up ? "" : "not ");
5876
5877
3.34k
    if (ncp_state_is_interface_up(get_ncp_state()) && !is_if_up) {
5878
2.25k
      change_ncp_state(mIsCommissioned ? COMMISSIONED : OFFLINE);
5879
2.25k
    }
5880
5881
50.3k
  } else if (key == SPINEL_PROP_MESHCOP_COMMISSIONER_STATE) {
5882
970
    boost::any value;
5883
970
    int status;
5884
970
    status = unpack_commissioner_state(value_data_ptr, value_data_len, value);
5885
970
    if (status == kWPANTUNDStatus_Ok) {
5886
434
      syslog(LOG_INFO, "[-NCP-]: Thread Commissioner state is \"%s\"", any_to_string(value).c_str());
5887
434
    }
5888
5889
49.4k
  } else if (key == SPINEL_PROP_THREAD_ON_MESH_NETS) {
5890
12.9k
    handle_ncp_spinel_value_is_ON_MESH_NETS(value_data_ptr, value_data_len);
5891
5892
36.4k
  } else if (key == SPINEL_PROP_THREAD_OFF_MESH_ROUTES) {
5893
3.21k
    handle_ncp_spinel_value_is_OFF_MESH_ROUTES(value_data_ptr, value_data_len);
5894
5895
33.2k
  } else if (key == SPINEL_PROP_SERVER_SERVICES) {
5896
2.08k
    handle_ncp_spinel_value_is_SERVICES(value_data_ptr, value_data_len);
5897
5898
31.1k
  } else if (key == SPINEL_PROP_THREAD_ASSISTING_PORTS) {
5899
698
    bool is_assisting = (value_data_len != 0);
5900
698
    uint16_t assisting_port(0);
5901
5902
698
    if (is_assisting) {
5903
467
      int i;
5904
467
      syslog(LOG_NOTICE, "Network is joinable");
5905
1.21k
      while (value_data_len > 0) {
5906
1.04k
        i = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT16_S, &assisting_port);
5907
1.04k
        if (i <= 0) {
5908
305
          break;
5909
305
        }
5910
743
        syslog(LOG_NOTICE, "Assisting on port %d", assisting_port);
5911
743
        value_data_ptr += i;
5912
743
        value_data_len -= i;
5913
743
      }
5914
467
    } else {
5915
231
      syslog(LOG_NOTICE, "Network is not joinable");
5916
231
    }
5917
5918
30.4k
  } else if (key == SPINEL_PROP_JAM_DETECTED) {
5919
692
    bool jamDetected = false;
5920
5921
692
    spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_BOOL_S, &jamDetected);
5922
692
    signal_property_changed(kWPANTUNDProperty_JamDetectionStatus, jamDetected);
5923
5924
692
    if (jamDetected) {
5925
143
      syslog(LOG_NOTICE, "Signal jamming is detected");
5926
549
    } else {
5927
549
      syslog(LOG_NOTICE, "Signal jamming cleared");
5928
549
    }
5929
5930
29.7k
  } else if (key == SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL) {
5931
708
    uint8_t new_channel = 0;
5932
708
    spinel_ssize_t len;
5933
5934
708
    len = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT8_S, &new_channel);
5935
5936
708
    if ((len >= 0) && (new_channel != mChannelManagerNewChannel)) {
5937
267
      mChannelManagerNewChannel = new_channel;
5938
267
      signal_property_changed(kWPANTUNDProperty_ChannelManagerNewChannel, new_channel);
5939
267
      syslog(LOG_INFO, "[-NCP-]: ChannelManager about to switch to new channel %d", new_channel);
5940
267
    }
5941
5942
29.0k
  } else if (key == SPINEL_PROP_STREAM_RAW) {
5943
83
    if (mPcapManager.is_enabled()) {
5944
0
      const uint8_t* frame_ptr(NULL);
5945
0
      unsigned int frame_len(0);
5946
0
      const uint8_t* meta_ptr(NULL);
5947
0
      unsigned int meta_len(0);
5948
0
      spinel_ssize_t ret;
5949
0
      PcapPacket packet;
5950
0
      uint16_t flags = 0;
5951
5952
0
      packet.set_timestamp().set_dlt(PCAP_DLT_IEEE802_15_4);
5953
5954
      // Unpack the packet.
5955
0
      ret = spinel_datatype_unpack(
5956
0
        value_data_ptr,
5957
0
        value_data_len,
5958
0
        SPINEL_DATATYPE_DATA_WLEN_S SPINEL_DATATYPE_DATA_S,
5959
0
        &frame_ptr,
5960
0
        &frame_len,
5961
0
        &meta_ptr,
5962
0
        &meta_len
5963
0
      );
5964
5965
0
      require(ret > 0, bail);
5966
5967
      // Unpack the metadata.
5968
0
      ret = spinel_datatype_unpack(
5969
0
        meta_ptr,
5970
0
        meta_len,
5971
0
        SPINEL_DATATYPE_INT8_S     // RSSI/TXPower
5972
        SPINEL_DATATYPE_INT8_S     // Noise Floor
5973
0
        SPINEL_DATATYPE_UINT16_S,  // Flags
5974
0
        NULL,   // Ignore RSSI/TXPower
5975
0
        NULL, // Ignore Noise Floor
5976
0
        &flags
5977
0
      );
5978
5979
0
      __ASSERT_MACROS_check(ret > 0);
5980
5981
0
      if ((flags & SPINEL_MD_FLAG_TX) == SPINEL_MD_FLAG_TX)
5982
0
      {
5983
        // Ignore FCS for transmitted packets
5984
0
        frame_len -= 2;
5985
0
        packet.set_dlt(PCAP_DLT_IEEE802_15_4_NOFCS);
5986
0
      }
5987
5988
0
      mPcapManager.push_packet(
5989
0
        packet
5990
0
          .append_ppi_field(PCAP_PPI_TYPE_SPINEL, meta_ptr, meta_len)
5991
0
          .append_payload(frame_ptr, frame_len)
5992
0
      );
5993
0
    }
5994
5995
28.9k
  } else if (key == SPINEL_PROP_THREAD_TMF_PROXY_STREAM) {
5996
461
    const uint8_t* frame_ptr(NULL);
5997
461
    unsigned int frame_len(0);
5998
461
    uint16_t locator = 0;
5999
461
    uint16_t port = 0;
6000
461
    spinel_ssize_t ret;
6001
461
    Data data;
6002
6003
461
    ret = spinel_datatype_unpack(
6004
461
      value_data_ptr,
6005
461
      value_data_len,
6006
461
      SPINEL_DATATYPE_DATA_S SPINEL_DATATYPE_UINT16_S SPINEL_DATATYPE_UINT16_S,
6007
461
      &frame_ptr,
6008
461
      &frame_len,
6009
461
      &locator,
6010
461
      &port
6011
461
    );
6012
6013
461
    __ASSERT_MACROS_check(ret > 0);
6014
6015
    // Analyze the packet to determine if it should be dropped.
6016
461
    if ((ret > 0)) {
6017
      // append frame
6018
352
      data.append(frame_ptr, frame_len);
6019
      // pack the locator in big endian.
6020
352
      data.push_back(locator >> 8);
6021
352
      data.push_back(locator & 0xff);
6022
      // pack the port in big endian.
6023
352
      data.push_back(port >> 8);
6024
352
      data.push_back(port & 0xff);
6025
352
      signal_property_changed(kWPANTUNDProperty_TmfProxyStream, data);
6026
352
    }
6027
6028
28.5k
  } else if (key == SPINEL_PROP_THREAD_UDP_FORWARD_STREAM) {
6029
395
    const uint8_t* frame_ptr(NULL);
6030
395
    unsigned int frame_len(0);
6031
395
    uint16_t peer_port = 0;
6032
395
    in6_addr *peer_addr;
6033
395
    uint16_t sock_port = 0;
6034
395
    spinel_ssize_t ret;
6035
395
    Data data;
6036
6037
395
    ret = spinel_datatype_unpack(
6038
395
      value_data_ptr,
6039
395
      value_data_len,
6040
395
      SPINEL_DATATYPE_DATA_S
6041
      SPINEL_DATATYPE_UINT16_S    // Peer port
6042
      SPINEL_DATATYPE_IPv6ADDR_S  // Peer address
6043
395
      SPINEL_DATATYPE_UINT16_S,   // Sock port
6044
395
      &frame_ptr,
6045
395
      &frame_len,
6046
395
      &peer_port,
6047
395
      &peer_addr,
6048
395
      &sock_port
6049
395
    );
6050
6051
395
    __ASSERT_MACROS_check(ret > 0);
6052
6053
    // Analyze the packet to determine if it should be dropped.
6054
395
    if (ret > 0) {
6055
      // append frame
6056
174
      data.append(frame_ptr, frame_len);
6057
      // pack the locator in big endian.
6058
174
      data.push_back(peer_port >> 8);
6059
174
      data.push_back(peer_port & 0xff);
6060
174
      data.append(peer_addr->s6_addr, sizeof(*peer_addr));
6061
      // pack the port in big endian.
6062
174
      data.push_back(sock_port >> 8);
6063
174
      data.push_back(sock_port & 0xff);
6064
174
      signal_property_changed(kWPANTUNDProperty_UdpForwardStream, data);
6065
174
    }
6066
6067
28.1k
  } else if ((key == SPINEL_PROP_STREAM_NET) || (key == SPINEL_PROP_STREAM_NET_INSECURE)) {
6068
14.8k
    const uint8_t* frame_ptr(NULL);
6069
14.8k
    unsigned int frame_len(0);
6070
14.8k
    spinel_ssize_t ret;
6071
14.8k
    uint8_t frame_data_type = FRAME_TYPE_DATA;
6072
6073
14.8k
    if (SPINEL_PROP_STREAM_NET_INSECURE == key) {
6074
14.2k
      frame_data_type = FRAME_TYPE_INSECURE_DATA;
6075
14.2k
    }
6076
6077
14.8k
    ret = spinel_datatype_unpack(
6078
14.8k
      value_data_ptr,
6079
14.8k
      value_data_len,
6080
14.8k
      SPINEL_DATATYPE_DATA_S SPINEL_DATATYPE_DATA_S,
6081
14.8k
      &frame_ptr,
6082
14.8k
      &frame_len,
6083
14.8k
      NULL,
6084
14.8k
      NULL
6085
14.8k
    );
6086
6087
14.8k
    __ASSERT_MACROS_check(ret > 0);
6088
6089
    // Analyze the packet to determine if it should be dropped.
6090
14.8k
    if ((ret > 0) && should_forward_hostbound_frame(&frame_data_type, frame_ptr, frame_len)) {
6091
13.2k
      if (static_cast<bool>(mLegacyInterface) && (frame_data_type == FRAME_TYPE_LEGACY_DATA)) {
6092
0
        handle_alt_ipv6_from_ncp(frame_ptr, frame_len);
6093
13.2k
      } else {
6094
13.2k
        handle_normal_ipv6_from_ncp(frame_ptr, frame_len);
6095
13.2k
      }
6096
13.2k
    }
6097
14.8k
  } else if (key == SPINEL_PROP_THREAD_CHILD_TABLE) {
6098
459
    SpinelNCPTaskGetNetworkTopology::Table child_table;
6099
459
    SpinelNCPTaskGetNetworkTopology::Table::iterator it;
6100
459
    int num_children = 0;
6101
6102
459
    SpinelNCPTaskGetNetworkTopology::parse_child_table(value_data_ptr, value_data_len, child_table);
6103
6104
684
    for (it = child_table.begin(); it != child_table.end(); it++)
6105
225
    {
6106
225
      num_children++;
6107
225
      syslog(LOG_INFO, "[-NCP-] Child: %02d %s", num_children, it->get_as_string().c_str());
6108
225
    }
6109
459
    syslog(LOG_INFO, "[-NCP-] Child: Total %d child%s", num_children, (num_children > 1) ? "ren" : "");
6110
6111
12.8k
  } else if (key == SPINEL_PROP_THREAD_NEIGHBOR_TABLE) {
6112
190
    SpinelNCPTaskGetNetworkTopology::Table neigh_table;
6113
190
    SpinelNCPTaskGetNetworkTopology::Table::iterator it;
6114
190
    int num_neighbor = 0;
6115
6116
190
    SpinelNCPTaskGetNetworkTopology::parse_neighbor_table(value_data_ptr, value_data_len, neigh_table);
6117
6118
380
    for (it = neigh_table.begin(); it != neigh_table.end(); it++)
6119
190
    {
6120
190
      num_neighbor++;
6121
190
      syslog(LOG_INFO, "[-NCP-] Neighbor: %02d %s", num_neighbor, it->get_as_string().c_str());
6122
190
    }
6123
190
    syslog(LOG_INFO, "[-NCP-] Neighbor: Total %d neighbor%s", num_neighbor, (num_neighbor > 1) ? "s" : "");
6124
6125
12.6k
  } else if (key == SPINEL_PROP_THREAD_NEIGHBOR_TABLE_ERROR_RATES) {
6126
402
    SpinelNCPTaskGetNetworkTopology::Table neigh_table;
6127
402
    SpinelNCPTaskGetNetworkTopology::Table::iterator it;
6128
402
    int num_neighbor = 0;
6129
6130
402
    SpinelNCPTaskGetNetworkTopology::prase_neighbor_error_rates_table(value_data_ptr, value_data_len, neigh_table);
6131
6132
549
    for (it = neigh_table.begin(); it != neigh_table.end(); it++)
6133
147
    {
6134
147
      num_neighbor++;
6135
147
      syslog(LOG_INFO, "[-NCP-] Neighbor: %02d %s", num_neighbor, it->get_as_string().c_str());
6136
147
    }
6137
402
    syslog(LOG_INFO, "[-NCP-] Neighbor: Total %d neighbor%s", num_neighbor, (num_neighbor > 1) ? "s" : "");
6138
6139
12.2k
  } else if (key == SPINEL_PROP_THREAD_ROUTER_TABLE) {
6140
226
    SpinelNCPTaskGetNetworkTopology::Table router_table;
6141
226
    SpinelNCPTaskGetNetworkTopology::Table::iterator it;
6142
226
    int num_router = 0;
6143
6144
226
    SpinelNCPTaskGetNetworkTopology::parse_router_table(value_data_ptr, value_data_len, router_table);
6145
6146
408
    for (it = router_table.begin(); it != router_table.end(); it++)
6147
182
    {
6148
182
      num_router++;
6149
182
      syslog(LOG_INFO, "[-NCP-] Router: %02d %s", num_router, it->get_as_string().c_str());
6150
182
    }
6151
226
    syslog(LOG_INFO, "[-NCP-] Router: Total %d router%s", num_router, (num_router > 1) ? "s" : "");
6152
6153
6154
12.0k
  } else if (key == SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE) {
6155
1.28k
    boost::any value;
6156
1.28k
    if ((unpack_address_cache_table(value_data_ptr, value_data_len, value, false) == kWPANTUNDStatus_Ok)
6157
656
      && (value.type() == typeid(std::list<std::string>))
6158
1.28k
    ) {
6159
656
      std::list<std::string> list = boost::any_cast<std::list<std::string> >(value);
6160
656
      int num_entries = 0;
6161
6162
950
      for (std::list<std::string>::iterator it = list.begin(); it != list.end(); it++) {
6163
294
        num_entries++;
6164
294
        syslog(LOG_INFO, "[-NCP-] AddressCache: %02d %s", num_entries, it->c_str());
6165
294
      }
6166
656
      syslog(LOG_INFO, "[-NCP-] AddressCache: Total %d entr%s", num_entries, (num_entries > 1) ? "ies" : "y");
6167
656
    }
6168
6169
10.7k
  } else if (key == SPINEL_PROP_NET_PARTITION_ID) {
6170
78
    uint32_t paritition_id = 0;
6171
78
    spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT32_S, &paritition_id);
6172
78
    syslog(LOG_INFO, "[-NCP-] Partition id: %u (0x%x)", paritition_id, paritition_id);
6173
6174
10.6k
  } else if (key == SPINEL_PROP_THREAD_LEADER_NETWORK_DATA) {
6175
78
    char net_data_cstr_buf[540];
6176
78
    encode_data_into_string(value_data_ptr, value_data_len, net_data_cstr_buf, sizeof(net_data_cstr_buf), 0);
6177
78
    syslog(LOG_INFO, "[-NCP-] Leader network data: [%s]", net_data_cstr_buf);
6178
6179
10.5k
  } else if (key == SPINEL_PROP_RCP_VERSION) {
6180
603
    const char *rcp_version = NULL;
6181
603
    spinel_ssize_t len;
6182
6183
603
    len = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UTF8_S, &rcp_version);
6184
6185
603
    if (len > 0) {
6186
461
      mRcpVersion = std::string(rcp_version);
6187
461
      syslog(LOG_NOTICE, "[-NCP-]: RCP is running \"%s\"", rcp_version);
6188
461
    }
6189
6190
9.96k
  } else if (key == SPINEL_PROP_SLAAC_ENABLED) {
6191
426
    bool enabled;
6192
426
    spinel_ssize_t len;
6193
6194
426
    len = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_BOOL_S, &enabled);
6195
6196
426
    if (len > 0) {
6197
92
      syslog(LOG_NOTICE, "[-NCP-]: SLAAC %sabled", enabled ? "en" : "dis");
6198
92
      mNCPHandlesSLAAC = enabled;
6199
92
    }
6200
6201
9.54k
  } else if (key == SPINEL_PROP_MESHCOP_JOINER_STATE) {
6202
1.65k
    boost::any value;
6203
6204
1.65k
    if (unpack_meshcop_joiner_state(value_data_ptr, value_data_len, value) == kWPANTUNDStatus_Ok) {
6205
1.02k
      syslog(LOG_NOTICE, "[-NCP-]: Joiner state \"%s\"", any_to_string(value).c_str());
6206
1.02k
    }
6207
6208
7.89k
  } else if (key == SPINEL_PROP_THREAD_NETWORK_TIME) {
6209
354
    ValueMap result;
6210
354
    std::string result_as_string;
6211
6212
354
    if (unpack_thread_network_time_as_valmap(value_data_ptr, value_data_len, result) == kWPANTUNDStatus_Ok) {
6213
135
      if (unpack_thread_network_time_as_string(value_data_ptr, value_data_len, result_as_string) == kWPANTUNDStatus_Ok) {
6214
135
        syslog(LOG_INFO, "[-NCP-]: Network time update: %s", result_as_string.c_str());
6215
135
      } else {
6216
0
        syslog(LOG_WARNING, "[-NCP-]: Failed to extract network time update for logging");
6217
0
      }
6218
6219
135
      handle_network_time_update(result);
6220
219
    } else {
6221
219
      syslog(LOG_WARNING, "[-NCP-]: Failed to unpack network time update");
6222
219
    }
6223
6224
7.53k
  } else if (key == SPINEL_PROP_THREAD_LINK_METRICS_QUERY_RESULT) {
6225
406
    spinel_ssize_t len;
6226
406
    struct in6_addr *source = NULL;
6227
406
    std::string source_str;
6228
406
    uint8_t status;
6229
406
    std::string status_str;
6230
406
    const uint8_t *struct_in = NULL;
6231
406
    unsigned int struct_len = 0;
6232
6233
406
    mLinkMetricsQueryResult.clear();
6234
6235
    // Decode source and status
6236
406
    len = spinel_datatype_unpack(
6237
406
      value_data_ptr,
6238
406
      value_data_len,
6239
406
      (
6240
406
        SPINEL_DATATYPE_IPv6ADDR_S
6241
406
        SPINEL_DATATYPE_UINT8_S
6242
406
        SPINEL_DATATYPE_DATA_WLEN_S
6243
406
      ),
6244
406
      &source,
6245
406
      &status,
6246
406
      &struct_in,
6247
406
      &struct_len
6248
406
    );
6249
6250
406
    require(len >= 0, bail);
6251
205
    value_data_ptr += len;
6252
205
    value_data_len -= len;
6253
6254
205
    source_str = in6_addr_to_string(*source);
6255
205
    status_str = spinel_link_metrics_status_to_cstr(status);
6256
6257
205
    mLinkMetricsQueryResult[kWPANTUNDValueMapKey_LinkMetrics_Source] = source_str;
6258
205
    mLinkMetricsQueryResult[kWPANTUNDValueMapKey_LinkMetrics_Status] = status_str;
6259
6260
205
    unpack_link_metrics_as_val_map(struct_in, struct_len, mLinkMetricsQueryResult);
6261
6262
7.13k
  } else if (key == SPINEL_PROP_THREAD_LINK_METRICS_MGMT_RESPONSE) {
6263
850
    spinel_ssize_t len;
6264
850
    struct in6_addr *source = NULL;
6265
850
    std::string source_str;
6266
850
    uint8_t status;
6267
850
    std::string status_str;
6268
6269
    // Decode source and status
6270
850
    len = spinel_datatype_unpack(
6271
850
      value_data_ptr,
6272
850
      value_data_len,
6273
850
      (
6274
850
        SPINEL_DATATYPE_IPv6ADDR_S
6275
850
        SPINEL_DATATYPE_UINT8_S
6276
850
      ),
6277
850
      &source,
6278
850
      &status
6279
850
    );
6280
6281
850
    require(len >= 0, bail);
6282
450
    value_data_ptr += len;
6283
450
    value_data_len -= len;
6284
6285
450
    source_str = in6_addr_to_string(*source);
6286
450
    status_str = spinel_link_metrics_status_to_cstr(status);
6287
6288
450
    mLinkMetricsMgmtResponse[kWPANTUNDValueMapKey_LinkMetrics_Source] = source_str;
6289
450
    mLinkMetricsMgmtResponse[kWPANTUNDValueMapKey_LinkMetrics_Status] = status_str;
6290
6291
450
    syslog(LOG_INFO, "Link Metrics Mqmt Response: %s (src: %s)", status_str.c_str(), source_str.c_str());
6292
6293
6.28k
  } else if (key == SPINEL_PROP_THREAD_LINK_METRICS_MGMT_ENH_ACK_IE) {
6294
1.06k
    spinel_ssize_t len;
6295
1.06k
    uint16_t short_addr = 0;
6296
1.06k
    const spinel_eui64_t *eui64 = NULL;
6297
1.06k
    const uint8_t *struct_in = NULL;
6298
1.06k
    unsigned int struct_len = 0;
6299
6300
1.06k
    mLinkMetricsLastEnhAckIe.clear();
6301
6302
1.06k
    len = spinel_datatype_unpack(
6303
1.06k
      value_data_ptr,
6304
1.06k
      value_data_len,
6305
1.06k
      (
6306
1.06k
        SPINEL_DATATYPE_UINT16_S
6307
1.06k
        SPINEL_DATATYPE_EUI64_S
6308
1.06k
        SPINEL_DATATYPE_DATA_WLEN_S
6309
1.06k
      ),
6310
1.06k
      &short_addr,
6311
1.06k
      &eui64,
6312
1.06k
      &struct_in,
6313
1.06k
      &struct_len
6314
1.06k
    );
6315
6316
1.06k
    require(len >= 0, bail);
6317
788
    value_data_ptr += len;
6318
788
    value_data_len -= len;
6319
6320
788
    syslog(LOG_DEBUG, "Received Link Metrics Enh-ACK IE from 0x%02x", short_addr);
6321
6322
788
    unpack_link_metrics_as_val_map(value_data_ptr, value_data_len, mLinkMetricsLastEnhAckIe);
6323
6324
5.22k
  } else if (key == SPINEL_PROP_THREAD_MLR_RESPONSE) {
6325
6326
1.29k
    mMulticastListenerRegistrationResponse.clear();
6327
6328
1.29k
    spinel_ssize_t len;
6329
1.29k
    uint8_t status;
6330
1.29k
    uint8_t mlr_status;
6331
1.29k
    const uint8_t *struct_in = NULL;
6332
1.29k
    unsigned int struct_len = 0;
6333
6334
1.29k
    len = spinel_datatype_unpack(
6335
1.29k
      value_data_ptr,
6336
1.29k
      value_data_len,
6337
1.29k
      (
6338
1.29k
        SPINEL_DATATYPE_UINT8_S
6339
1.29k
        SPINEL_DATATYPE_UINT8_S
6340
1.29k
      ),
6341
1.29k
      &status,
6342
1.29k
      &mlr_status
6343
1.29k
    );
6344
6345
1.29k
    require(len >= 0, bail);
6346
958
    value_data_ptr += len;
6347
958
    value_data_len -= len;
6348
6349
958
    mMulticastListenerRegistrationResponse[kWPANTUNDValueMapKey_ThreadMlrResponse_Status] = status;
6350
958
    mMulticastListenerRegistrationResponse[kWPANTUNDValueMapKey_ThreadMlrResponse_MlrStatus] = mlr_status;
6351
6352
958
    std::list<std::string> addrList;
6353
6354
958
    len = spinel_datatype_unpack(
6355
958
      value_data_ptr,
6356
958
      value_data_len,
6357
958
      SPINEL_DATATYPE_DATA_WLEN_S,
6358
958
      &struct_in,
6359
958
      &struct_len
6360
958
    );
6361
6362
958
    require(len >= 0, bail);
6363
885
    value_data_ptr += len;
6364
885
    value_data_len -= len;
6365
6366
1.14k
    while (struct_len != 0)
6367
463
    {
6368
463
      const in6_addr * failed_addr;
6369
6370
463
      len = spinel_datatype_unpack(
6371
463
        struct_in,
6372
463
        struct_len,
6373
463
        SPINEL_DATATYPE_IPv6ADDR_S,
6374
463
        &failed_addr
6375
463
      );
6376
6377
463
      require(len > 0, bail);
6378
6379
257
      struct_in  += len;
6380
257
      struct_len -= len;
6381
6382
257
      addrList.push_back(in6_addr_to_string(*failed_addr));
6383
257
    }
6384
6385
679
    mMulticastListenerRegistrationResponse[kWPANTUNDValueMapKey_ThreadMlrResponse_Addresses] = addrList;
6386
6387
679
    syslog(LOG_DEBUG, "Received Multicast Listener Registration Response status=%u mlr_status=%u",
6388
679
      (unsigned)status, (unsigned)mlr_status);
6389
679
  }
6390
6391
123k
bail:
6392
123k
  process_event(EVENT_NCP_PROP_VALUE_IS, key, original_value_data_ptr, original_value_data_len);
6393
123k
}
6394
6395
void
6396
SpinelNCPInstance::handle_ncp_spinel_value_inserted(spinel_prop_key_t key, const uint8_t* value_data_ptr, spinel_size_t value_data_len)
6397
22.5k
{
6398
22.5k
  if (key == SPINEL_PROP_IPV6_ADDRESS_TABLE) {
6399
8.84k
      struct in6_addr *addr = NULL;
6400
8.84k
      uint8_t prefix_len = 0;
6401
8.84k
      uint32_t valid_lifetime = 0xFFFFFFFF;
6402
8.84k
      uint32_t preferred_lifetime = 0xFFFFFFFF;
6403
6404
8.84k
      spinel_datatype_unpack(value_data_ptr, value_data_len, "6CLL", &addr, &prefix_len, &valid_lifetime, &preferred_lifetime);
6405
6406
8.84k
      if (addr != NULL) {
6407
4.52k
        if (!should_filter_address(*addr, prefix_len)) {
6408
4.22k
          unicast_address_was_added(kOriginThreadNCP, *addr, prefix_len, valid_lifetime, preferred_lifetime);
6409
4.22k
        }
6410
4.52k
      }
6411
6412
13.7k
  } else if (key == SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE) {
6413
8.00k
    struct in6_addr *addr = NULL;
6414
6415
8.00k
    spinel_datatype_unpack(value_data_ptr, value_data_len, "6", &addr);
6416
6417
8.00k
    if ((addr != NULL) && !IN6_IS_ADDR_UNSPECIFIED(addr)) {
6418
4.67k
      multicast_address_was_joined(kOriginThreadNCP, *addr);
6419
4.67k
    }
6420
6421
8.00k
  } else if (key == SPINEL_PROP_THREAD_CHILD_TABLE) {
6422
168
    SpinelNCPTaskGetNetworkTopology::TableEntry child_entry;
6423
168
    int status;
6424
6425
168
    status = SpinelNCPTaskGetNetworkTopology::parse_child_entry(value_data_ptr, value_data_len, child_entry);
6426
6427
168
    if (status == kWPANTUNDStatus_Ok) {
6428
101
      syslog(LOG_INFO, "[-NCP-]: ChildTable entry added: %s", child_entry.get_as_string().c_str());
6429
101
    }
6430
6431
5.54k
  } else if (key == SPINEL_PROP_THREAD_NEIGHBOR_TABLE) {
6432
175
    SpinelNCPTaskGetNetworkTopology::TableEntry neighbor_entry;
6433
175
    int status;
6434
6435
175
    status = SpinelNCPTaskGetNetworkTopology::parse_neighbor_entry(value_data_ptr, value_data_len, neighbor_entry);
6436
6437
175
    if (status == kWPANTUNDStatus_Ok) {
6438
82
      syslog(LOG_INFO, "[-NCP-]: Neighbor(Router) entry added: %s", neighbor_entry.get_as_string().c_str());
6439
82
    }
6440
6441
5.36k
  } else if (key == SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN_RESULT) {
6442
1.97k
    spinel_ssize_t len;
6443
1.97k
    uint32_t channel_mask;
6444
1.97k
    const uint8_t *energy_data = NULL;
6445
1.97k
    unsigned int energy_data_len = 0;
6446
1.97k
    ValueMap entry;
6447
6448
1.97k
    len = spinel_datatype_unpack(
6449
1.97k
      value_data_ptr,
6450
1.97k
      value_data_len,
6451
1.97k
      (
6452
1.97k
        SPINEL_DATATYPE_UINT32_S
6453
1.97k
        SPINEL_DATATYPE_DATA_WLEN_S
6454
1.97k
      ),
6455
1.97k
      &channel_mask,
6456
1.97k
      &energy_data,
6457
1.97k
      &energy_data_len
6458
1.97k
    );
6459
6460
1.97k
    __ASSERT_MACROS_check(len > 0);
6461
6462
1.97k
    entry[kWPANTUNDValueMapKey_CommrEnergyScanResult_ChannelMask] = channel_mask;
6463
1.97k
    entry[kWPANTUNDValueMapKey_CommrEnergyScanResult_Data] = Data(energy_data, energy_data_len);
6464
6465
1.97k
    if (mCommissionerEnergyScanResult.size() == kMaxCommissionerEnergyScanResultEntries) {
6466
609
      mCommissionerEnergyScanResult.pop_front();
6467
609
    }
6468
6469
1.97k
    mCommissionerEnergyScanResult.push_back(entry);
6470
6471
3.39k
  } else if (key == SPINEL_PROP_MESHCOP_COMMISSIONER_PAN_ID_CONFLICT_RESULT) {
6472
1.48k
    spinel_ssize_t len;
6473
1.48k
    uint16_t panid;
6474
1.48k
    uint32_t channel_mask;
6475
1.48k
    ValueMap entry;
6476
6477
1.48k
    len = spinel_datatype_unpack(
6478
1.48k
      value_data_ptr,
6479
1.48k
      value_data_len,
6480
1.48k
      (
6481
1.48k
        SPINEL_DATATYPE_UINT16_S
6482
1.48k
        SPINEL_DATATYPE_UINT32_S
6483
1.48k
      ),
6484
1.48k
      &panid,
6485
1.48k
      &channel_mask
6486
1.48k
    );
6487
6488
1.48k
    __ASSERT_MACROS_check(len > 0);
6489
6490
1.48k
    entry[kWPANTUNDValueMapKey_CommrPanIdConflict_PanId] = panid;
6491
1.48k
    entry[kWPANTUNDValueMapKey_CommrPanIdConflict_ChannelMask] = channel_mask;
6492
6493
1.48k
    if (mCommissionerPanIdConflictResult.size() == kMaxCommissionerPanIdConflictResultEntries) {
6494
381
      mCommissionerPanIdConflictResult.pop_front();
6495
381
    }
6496
6497
1.48k
    mCommissionerPanIdConflictResult.push_back(entry);
6498
1.48k
  }
6499
6500
22.5k
  process_event(EVENT_NCP_PROP_VALUE_INSERTED, key, value_data_ptr, value_data_len);
6501
22.5k
}
6502
6503
void
6504
SpinelNCPInstance::handle_ncp_spinel_value_removed(spinel_prop_key_t key, const uint8_t* value_data_ptr, spinel_size_t value_data_len)
6505
1.07k
{
6506
1.07k
  if (key == SPINEL_PROP_THREAD_CHILD_TABLE) {
6507
195
    SpinelNCPTaskGetNetworkTopology::TableEntry child_entry;
6508
195
    int status;
6509
6510
195
    status = SpinelNCPTaskGetNetworkTopology::parse_child_entry(value_data_ptr, value_data_len, child_entry);
6511
6512
195
    if (status == kWPANTUNDStatus_Ok) {
6513
74
      syslog(LOG_INFO, "[-NCP-]: ChildTable entry removed: %s", child_entry.get_as_string().c_str());
6514
74
    }
6515
6516
880
  } else if (key == SPINEL_PROP_THREAD_NEIGHBOR_TABLE) {
6517
494
    SpinelNCPTaskGetNetworkTopology::TableEntry neighbor_entry;
6518
494
    int status;
6519
6520
494
    status = SpinelNCPTaskGetNetworkTopology::parse_neighbor_entry(value_data_ptr, value_data_len, neighbor_entry);
6521
6522
494
    if (status == kWPANTUNDStatus_Ok) {
6523
86
      syslog(LOG_INFO, "[-NCP-]: Neighbor(Router) entry removed: %s", neighbor_entry.get_as_string().c_str());
6524
86
    }
6525
6526
494
  }
6527
6528
1.07k
  process_event(EVENT_NCP_PROP_VALUE_REMOVED, key, value_data_ptr, value_data_len);
6529
1.07k
}
6530
6531
void
6532
SpinelNCPInstance::handle_ncp_state_change(NCPState new_ncp_state, NCPState old_ncp_state)
6533
19.0k
{
6534
19.0k
  NCPInstanceBase::handle_ncp_state_change(new_ncp_state, old_ncp_state);
6535
6536
19.0k
  if ( ncp_state_is_joining_or_joined(old_ncp_state)
6537
5.66k
    && (new_ncp_state == OFFLINE)
6538
19.0k
  ) {
6539
    // Mark this as false so that if we are actually doing
6540
    // a pcap right now it will force the details to be updated
6541
    // on the NCP at the next run through the main loop. This
6542
    // allows us to go back to promiscuous-mode sniffing at
6543
    // disconnect
6544
1.76k
    mIsPcapInProgress = false;
6545
1.76k
  }
6546
6547
19.0k
  if (ncp_state_is_associated(new_ncp_state)
6548
2.68k
   && !ncp_state_is_associated(old_ncp_state)
6549
19.0k
  ) {
6550
2.15k
    mIsCommissioned = true;
6551
2.15k
    start_new_task(SpinelNCPTaskSendCommand::Factory(this)
6552
2.15k
      .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_MAC_15_4_LADDR))
6553
2.15k
      .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_IPV6_ML_ADDR))
6554
2.15k
      .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_NET_XPANID))
6555
2.15k
      .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_MAC_15_4_PANID))
6556
2.15k
      .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_PHY_CHAN))
6557
2.15k
      .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_IPV6_ADDRESS_TABLE))
6558
2.15k
      .finish()
6559
2.15k
    );
6560
16.8k
  } else if (ncp_state_is_joining(new_ncp_state)
6561
2.92k
   && !ncp_state_is_joining(old_ncp_state)
6562
16.8k
  ) {
6563
2.82k
    if (!buffer_is_nonzero(mNCPV6Prefix, 8)) {
6564
2.74k
      start_new_task(SpinelNCPTaskSendCommand::Factory(this)
6565
2.74k
        .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_IPV6_ML_PREFIX))
6566
2.74k
        .finish()
6567
2.74k
      );
6568
2.74k
    }
6569
2.82k
  }
6570
19.0k
}
6571
6572
void
6573
SpinelNCPInstance::handle_ncp_spinel_callback(unsigned int command, const uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len)
6574
176k
{
6575
176k
  switch (command) {
6576
126k
  case SPINEL_CMD_PROP_VALUE_IS:
6577
135k
  case SPINEL_CMD_PROP_VALUE_INSERTED:
6578
136k
  case SPINEL_CMD_PROP_VALUE_REMOVED:
6579
136k
    {
6580
136k
      spinel_prop_key_t key = SPINEL_PROP_LAST_STATUS;
6581
136k
      uint8_t* value_data_ptr = NULL;
6582
136k
      spinel_size_t value_data_len = 0;
6583
136k
      spinel_ssize_t ret;
6584
6585
136k
      ret = spinel_datatype_unpack(cmd_data_ptr, cmd_data_len, "CiiD", NULL, NULL, &key, &value_data_ptr, &value_data_len);
6586
6587
136k
      __ASSERT_MACROS_check(ret != -1);
6588
6589
136k
      if (ret == -1) {
6590
195
        break;
6591
195
      }
6592
6593
136k
      switch (command) {
6594
126k
      case SPINEL_CMD_PROP_VALUE_IS:
6595
126k
        handle_ncp_spinel_value_is(key, value_data_ptr, value_data_len);
6596
126k
        break;
6597
8.83k
      case SPINEL_CMD_PROP_VALUE_INSERTED:
6598
8.83k
        handle_ncp_spinel_value_inserted(key, value_data_ptr, value_data_len);
6599
8.83k
        break;
6600
1.07k
      case SPINEL_CMD_PROP_VALUE_REMOVED:
6601
1.07k
        handle_ncp_spinel_value_removed(key, value_data_ptr, value_data_len);
6602
1.07k
        break;
6603
136k
      }
6604
136k
    }
6605
136k
    break;
6606
6607
136k
  default:
6608
39.6k
    process_event(EVENT_NCP(command), cmd_data_ptr[0], cmd_data_ptr, cmd_data_len);
6609
176k
  }
6610
176k
}
6611
6612
bool
6613
SpinelNCPInstance::should_filter_address(const struct in6_addr &addr, uint8_t prefix_len)
6614
8.55k
{
6615
8.55k
  static const uint8_t service_aloc_start = 0x10;
6616
8.55k
  static const uint8_t service_aloc_end = 0x2F;
6617
8.55k
  static const uint8_t rloc_bytes[] = {0x00,0x00,0x00,0xFF,0xFE,0x00};
6618
8.55k
  bool should_filter = false;
6619
6620
8.55k
  if (mFilterRLOCAddresses) {
6621
    // Filter RLOC link-local or mesh-local addresses
6622
6623
8.55k
    if (0 == memcmp(rloc_bytes, addr.s6_addr + 8, sizeof(rloc_bytes))) {
6624
2.15k
      if( addr.s6_addr[ 14 ] == 0xFC ) {
6625
361
        if (addr.s6_addr[15] < service_aloc_start || addr.s6_addr[15] > service_aloc_end)
6626
132
        {
6627
132
          should_filter = mFilterALOCAddresses;
6628
132
        }
6629
1.79k
      } else {
6630
1.79k
        if (IN6_IS_ADDR_LINKLOCAL(&addr)) {
6631
73
          should_filter = true;
6632
73
        }
6633
6634
1.79k
        if (buffer_is_nonzero(mNCPV6Prefix, sizeof(mNCPV6Prefix))
6635
1.52k
          && (0 == memcmp(mNCPV6Prefix, &addr, sizeof(mNCPV6Prefix)))
6636
1.79k
        ) {
6637
129
          should_filter = true;
6638
129
        }
6639
1.79k
      }
6640
2.15k
    }
6641
8.55k
  }
6642
6643
8.55k
  return should_filter;
6644
8.55k
}
6645
6646
void
6647
SpinelNCPInstance::filter_addresses(void)
6648
924
{
6649
924
  std::map<struct in6_addr, UnicastAddressEntry> unicast_addresses(mUnicastAddresses);
6650
924
  std::map<struct in6_addr, UnicastAddressEntry>::iterator iter;
6651
6652
  // We create a copy of mUnicastAddress map to iterate over
6653
  // since `mUnicastAddresses` entries can be removed while
6654
  // we filter and remove addresses.
6655
6656
4.95k
  for (iter = unicast_addresses.begin(); iter != unicast_addresses.end(); ++iter) {
6657
4.03k
    if (!iter->second.is_from_ncp()) {
6658
0
      continue;
6659
0
    }
6660
6661
4.03k
    if (should_filter_address(iter->first, iter->second.get_prefix_len())) {
6662
43
      unicast_address_was_removed(kOriginThreadNCP, iter->first);
6663
43
    }
6664
4.03k
  }
6665
924
}
6666
6667
void
6668
SpinelNCPInstance::add_unicast_address_on_ncp(const struct in6_addr &addr, uint8_t prefix_len, CallbackWithStatus cb)
6669
9.97k
{
6670
9.97k
  SpinelNCPTaskSendCommand::Factory factory(this);
6671
6672
9.97k
  syslog(LOG_NOTICE, "Adding address \"%s/%d\" to NCP", in6_addr_to_string(addr).c_str(), prefix_len);
6673
6674
9.97k
  factory.set_callback(cb);
6675
6676
9.97k
  factory.add_command(
6677
9.97k
    SpinelPackData(
6678
9.97k
      SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(
6679
9.97k
        SPINEL_DATATYPE_IPv6ADDR_S   // Address
6680
9.97k
        SPINEL_DATATYPE_UINT8_S      // Prefix Length
6681
9.97k
        SPINEL_DATATYPE_UINT32_S     // Valid Lifetime
6682
9.97k
        SPINEL_DATATYPE_UINT32_S     // Preferred Lifetime
6683
9.97k
      ),
6684
9.97k
      SPINEL_PROP_IPV6_ADDRESS_TABLE,
6685
9.97k
      &addr,
6686
9.97k
      prefix_len,
6687
9.97k
      UINT32_MAX,
6688
9.97k
      UINT32_MAX
6689
9.97k
    )
6690
9.97k
  );
6691
6692
9.97k
  start_new_task(factory.finish());
6693
9.97k
}
6694
6695
void
6696
SpinelNCPInstance::remove_unicast_address_on_ncp(const struct in6_addr& addr, uint8_t prefix_len, CallbackWithStatus cb)
6697
7.12k
{
6698
7.12k
  SpinelNCPTaskSendCommand::Factory factory(this);
6699
6700
7.12k
  syslog(LOG_NOTICE, "Removing address \"%s/%d\" from NCP", in6_addr_to_string(addr).c_str(), prefix_len);
6701
6702
7.12k
  factory.set_callback(cb);
6703
6704
7.12k
  factory.add_command(
6705
7.12k
    SpinelPackData(
6706
7.12k
      SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(
6707
7.12k
        SPINEL_DATATYPE_IPv6ADDR_S   // Address
6708
7.12k
        SPINEL_DATATYPE_UINT8_S      // Prefix
6709
7.12k
      ),
6710
7.12k
      SPINEL_PROP_IPV6_ADDRESS_TABLE,
6711
7.12k
      &addr,
6712
7.12k
      prefix_len
6713
7.12k
    )
6714
7.12k
  );
6715
6716
7.12k
  start_new_task(factory.finish());
6717
7.12k
}
6718
6719
void
6720
SpinelNCPInstance::add_multicast_address_on_ncp(const struct in6_addr &addr, CallbackWithStatus cb)
6721
0
{
6722
0
  SpinelNCPTaskSendCommand::Factory factory(this);
6723
6724
0
  syslog(LOG_NOTICE, "Adding multicast address \"%s\" to NCP", in6_addr_to_string(addr).c_str());
6725
6726
0
  factory.set_callback(cb);
6727
6728
0
  factory.add_command(
6729
0
    SpinelPackData(
6730
0
      SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(
6731
0
        SPINEL_DATATYPE_IPv6ADDR_S   // Address
6732
0
      ),
6733
0
      SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE,
6734
0
      &addr
6735
0
    )
6736
0
  );
6737
6738
0
  start_new_task(factory.finish());
6739
0
}
6740
6741
void
6742
SpinelNCPInstance::remove_multicast_address_on_ncp(const struct in6_addr &addr, CallbackWithStatus cb)
6743
0
{
6744
0
  SpinelNCPTaskSendCommand::Factory factory(this);
6745
6746
0
  syslog(LOG_NOTICE, "Removing multicast address \"%s\" from NCP", in6_addr_to_string(addr).c_str());
6747
6748
0
  factory.set_callback(cb);
6749
6750
0
  factory.add_command(
6751
0
    SpinelPackData(
6752
0
      SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(
6753
0
        SPINEL_DATATYPE_IPv6ADDR_S   // Address
6754
0
      ),
6755
0
      SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE,
6756
0
      &addr
6757
0
    )
6758
0
  );
6759
6760
0
  start_new_task(factory.finish());
6761
0
}
6762
6763
void
6764
SpinelNCPInstance::add_service_on_ncp(uint32_t enterprise_number, const Data& service_data, bool stable,
6765
  const Data& server_data, CallbackWithStatus cb)
6766
0
{
6767
0
  SpinelNCPTaskSendCommand::Factory factory(this);
6768
6769
0
  syslog(LOG_NOTICE, "Adding service with enterprise number:%u to NCP", enterprise_number);
6770
6771
0
  if (mCapabilities.count(SPINEL_CAP_THREAD_SERVICE) > 0) {
6772
0
    factory.set_lock_property(SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE);
6773
0
    factory.set_callback(cb);
6774
6775
0
    factory.add_command(SpinelPackData(
6776
0
      SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(
6777
0
        SPINEL_DATATYPE_UINT32_S    // Enterprise Number
6778
0
        SPINEL_DATATYPE_DATA_WLEN_S // Service Data
6779
0
        SPINEL_DATATYPE_BOOL_S      // stable
6780
0
        SPINEL_DATATYPE_DATA_WLEN_S // Server Data
6781
0
      ),
6782
0
      SPINEL_PROP_SERVER_SERVICES,
6783
0
      enterprise_number,
6784
0
      service_data.data(),
6785
0
      service_data.size(),
6786
0
      stable,
6787
0
      server_data.data(),
6788
0
      server_data.size()
6789
0
    ));
6790
6791
0
    start_new_task(factory.finish());
6792
0
  } else {
6793
0
    syslog(LOG_ERR, "%s capability not supported", spinel_capability_to_cstr(SPINEL_CAP_THREAD_SERVICE));
6794
0
    cb(kWPANTUNDStatus_FeatureNotSupported);
6795
0
  }
6796
0
}
6797
6798
void
6799
SpinelNCPInstance::remove_service_on_ncp(uint32_t enterprise_number, const Data& service_data, CallbackWithStatus cb)
6800
0
{
6801
0
  SpinelNCPTaskSendCommand::Factory factory(this);
6802
6803
0
  syslog(LOG_NOTICE, "Removing service with enterprise number:%u from NCP", enterprise_number);
6804
6805
0
  if (mCapabilities.count(SPINEL_CAP_THREAD_SERVICE) > 0) {
6806
0
    factory.set_lock_property(SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE);
6807
0
    factory.set_callback(cb);
6808
6809
0
    factory.add_command(SpinelPackData(
6810
0
      SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(
6811
0
        SPINEL_DATATYPE_UINT32_S    // Enterprise Number
6812
0
        SPINEL_DATATYPE_DATA_WLEN_S // Service Data
6813
0
      ),
6814
0
      SPINEL_PROP_SERVER_SERVICES,
6815
0
      enterprise_number,
6816
0
      service_data.data(),
6817
0
      service_data.size()
6818
0
    ));
6819
6820
0
    start_new_task(factory.finish());
6821
0
  } else {
6822
0
    syslog(LOG_ERR, "%s capability not supported", spinel_capability_to_cstr(SPINEL_CAP_THREAD_SERVICE));
6823
0
    cb(kWPANTUNDStatus_FeatureNotSupported);
6824
0
  }
6825
0
}
6826
6827
void
6828
SpinelNCPInstance::add_on_mesh_prefix_on_ncp(const struct in6_addr &prefix, uint8_t prefix_len, uint16_t flags,
6829
  bool stable, CallbackWithStatus cb)
6830
0
{
6831
0
  SpinelNCPTaskSendCommand::Factory factory(this);
6832
6833
0
  syslog(LOG_NOTICE, "Adding on-mesh prefix \"%s/%d\" to NCP", in6_addr_to_string(prefix).c_str(), prefix_len);
6834
6835
0
  factory.set_lock_property(SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
6836
0
  factory.set_callback(cb);
6837
6838
0
  factory.add_command(SpinelPackData(
6839
0
    SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(
6840
0
      SPINEL_DATATYPE_IPv6ADDR_S
6841
0
      SPINEL_DATATYPE_UINT8_S
6842
0
      SPINEL_DATATYPE_BOOL_S
6843
0
      SPINEL_DATATYPE_UINT8_S
6844
0
      SPINEL_DATATYPE_BOOL_S
6845
0
      SPINEL_DATATYPE_UINT16_S
6846
0
      SPINEL_DATATYPE_UINT8_S
6847
0
    ),
6848
0
    SPINEL_PROP_THREAD_ON_MESH_NETS,
6849
0
    &prefix,
6850
0
    prefix_len,
6851
0
    stable,
6852
0
    flags & 0xff,
6853
0
    false,
6854
0
    0,
6855
0
    (flags >> 8) & 0xff
6856
0
  ));
6857
6858
0
  start_new_task(factory.finish());
6859
0
}
6860
6861
void
6862
SpinelNCPInstance::remove_on_mesh_prefix_on_ncp(const struct in6_addr &prefix, uint8_t prefix_len, uint16_t flags,
6863
  bool stable, CallbackWithStatus cb)
6864
0
{
6865
0
  SpinelNCPTaskSendCommand::Factory factory(this);
6866
6867
0
  syslog(LOG_NOTICE, "Removing on-mesh prefix \"%s/%d\" from NCP", in6_addr_to_string(prefix).c_str(), prefix_len);
6868
6869
0
  factory.set_lock_property(SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
6870
0
  factory.set_callback(cb);
6871
6872
0
  factory.add_command(SpinelPackData(
6873
0
    SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(
6874
0
      SPINEL_DATATYPE_IPv6ADDR_S
6875
0
      SPINEL_DATATYPE_UINT8_S
6876
0
      SPINEL_DATATYPE_BOOL_S
6877
0
      SPINEL_DATATYPE_UINT8_S
6878
0
    ),
6879
0
    SPINEL_PROP_THREAD_ON_MESH_NETS,
6880
0
    &prefix,
6881
0
    prefix_len,
6882
0
    stable,
6883
0
    flags & 0xff
6884
0
  ));
6885
6886
0
  start_new_task(factory.finish());
6887
0
}
6888
6889
void
6890
SpinelNCPInstance::add_route_on_ncp(const struct in6_addr &route, uint8_t prefix_len, RoutePreference preference,
6891
  bool stable, CallbackWithStatus cb)
6892
0
{
6893
0
  SpinelNCPTaskSendCommand::Factory factory(this);
6894
6895
0
  syslog(LOG_NOTICE, "Adding off-mesh route \"%s/%d\" with preference %s to NCP", in6_addr_to_string(route).c_str(),
6896
0
    prefix_len, NCPControlInterface::external_route_priority_to_string(preference).c_str());
6897
6898
0
  factory.set_lock_property(SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
6899
0
  factory.set_callback(cb);
6900
6901
0
  factory.add_command(SpinelPackData(
6902
0
    SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(
6903
0
      SPINEL_DATATYPE_IPv6ADDR_S
6904
0
      SPINEL_DATATYPE_UINT8_S
6905
0
      SPINEL_DATATYPE_BOOL_S
6906
0
      SPINEL_DATATYPE_UINT8_S
6907
0
    ),
6908
0
    SPINEL_PROP_THREAD_OFF_MESH_ROUTES,
6909
0
    &route,
6910
0
    prefix_len,
6911
0
    stable,
6912
0
    convert_route_preference_to_flags(preference)
6913
0
  ));
6914
6915
0
  start_new_task(factory.finish());
6916
0
}
6917
6918
void
6919
SpinelNCPInstance::remove_route_on_ncp(const struct in6_addr &route, uint8_t prefix_len, RoutePreference preference,
6920
  bool stable, CallbackWithStatus cb)
6921
0
{
6922
0
  SpinelNCPTaskSendCommand::Factory factory(this);
6923
6924
0
  syslog(LOG_NOTICE, "Removing off-mesh route \"%s/%d\" with preference %s from NCP", in6_addr_to_string(route).c_str(),
6925
0
    prefix_len, NCPControlInterface::external_route_priority_to_string(preference).c_str());
6926
6927
0
  factory.set_lock_property(SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
6928
0
  factory.set_callback(cb);
6929
6930
0
  factory.add_command(SpinelPackData(
6931
0
    SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(
6932
0
      SPINEL_DATATYPE_IPv6ADDR_S
6933
0
      SPINEL_DATATYPE_UINT8_S
6934
0
      SPINEL_DATATYPE_BOOL_S
6935
0
      SPINEL_DATATYPE_UINT8_S
6936
0
    ),
6937
0
    SPINEL_PROP_THREAD_OFF_MESH_ROUTES,
6938
0
    &route,
6939
0
    prefix_len,
6940
0
    stable,
6941
0
    convert_route_preference_to_flags(preference)
6942
0
  ));
6943
6944
0
  start_new_task(factory.finish());
6945
0
}
6946
6947
SpinelNCPInstance::RoutePreference
6948
SpinelNCPInstance::convert_flags_to_route_preference(uint8_t flags)
6949
5.62k
{
6950
5.62k
  RoutePreference preference = NCPControlInterface::ROUTE_MEDIUM_PREFERENCE;
6951
6952
5.62k
  switch (flags & SPINEL_NET_FLAG_PREFERENCE_MASK) {
6953
881
  case SPINEL_ROUTE_PREFERENCE_HIGH:
6954
881
    preference = NCPControlInterface::ROUTE_HIGH_PREFERENCE;
6955
881
    break;
6956
6957
2.21k
  case SPINEL_ROUTE_PREFERENCE_MEDIUM:
6958
2.21k
    preference = NCPControlInterface::ROUTE_MEDIUM_PREFERENCE;
6959
2.21k
    break;
6960
6961
1.84k
  case SPINEL_ROUTE_PREFERENCE_LOW:
6962
1.84k
    preference = NCPControlInterface::ROUTE_LOW_PREFRENCE;
6963
1.84k
    break;
6964
6965
683
  default:
6966
683
    syslog(LOG_WARNING, "Invalid RoutePreference flag 0x%02x (using MEDIUM instead)", flags);
6967
683
    break;
6968
5.62k
  }
6969
6970
5.62k
  return preference;
6971
5.62k
}
6972
6973
uint8_t
6974
SpinelNCPInstance::convert_route_preference_to_flags(RoutePreference preference)
6975
0
{
6976
0
  uint8_t flags = SPINEL_ROUTE_PREFERENCE_MEDIUM;
6977
6978
0
  switch (preference) {
6979
0
  case NCPControlInterface::ROUTE_HIGH_PREFERENCE:
6980
0
    flags = SPINEL_ROUTE_PREFERENCE_HIGH;
6981
0
    break;
6982
6983
0
  case NCPControlInterface::ROUTE_MEDIUM_PREFERENCE:
6984
0
    flags = SPINEL_ROUTE_PREFERENCE_MEDIUM;
6985
0
    break;
6986
6987
0
  case NCPControlInterface::ROUTE_LOW_PREFRENCE:
6988
0
    flags = SPINEL_ROUTE_PREFERENCE_LOW;
6989
0
    break;
6990
0
  }
6991
6992
0
  return flags;
6993
0
}
6994
6995
void
6996
SpinelNCPInstance::log_spinel_frame(SpinelFrameOrigin origin, const uint8_t *frame_ptr, spinel_size_t frame_len)
6997
229k
{
6998
229k
  int logmask = setlogmask(0);
6999
7000
229k
  setlogmask(logmask);
7001
7002
229k
  if (logmask & LOG_MASK(LOG_INFO)) {
7003
0
    std::string log;
7004
0
    uint8_t header = 0;
7005
0
    unsigned int command = 0;
7006
0
    const uint8_t *cmd_payload_ptr = NULL;
7007
0
    spinel_size_t cmd_payload_len = 0;
7008
0
    spinel_ssize_t read_len;
7009
0
    uint8_t tid;
7010
0
    const char *command_str;
7011
0
    const char *origin_str = (origin == kDriverToNCP) ? "[->NCP]" : "[NCP->]";
7012
7013
0
    read_len = spinel_datatype_unpack(frame_ptr, frame_len, "CiD", &header, &command, &cmd_payload_ptr,
7014
0
      &cmd_payload_len);
7015
0
    require_quiet(read_len > 0, bail);
7016
7017
0
    tid = SPINEL_HEADER_GET_TID(header);
7018
0
    command_str = spinel_command_to_cstr(command);
7019
7020
0
    switch (command) {
7021
0
    case SPINEL_CMD_NOOP:
7022
0
    case SPINEL_CMD_RESET:
7023
0
    case SPINEL_CMD_NET_CLEAR:
7024
0
      syslog(LOG_INFO, "%s (%d) %s", origin_str, tid, command_str);
7025
0
      break;
7026
7027
0
    case SPINEL_CMD_PROP_VALUE_GET:
7028
0
    case SPINEL_CMD_PROP_VALUE_SET:
7029
0
    case SPINEL_CMD_PROP_VALUE_INSERT:
7030
0
    case SPINEL_CMD_PROP_VALUE_REMOVE:
7031
0
    case SPINEL_CMD_PROP_VALUE_IS:
7032
0
    case SPINEL_CMD_PROP_VALUE_INSERTED:
7033
0
    case SPINEL_CMD_PROP_VALUE_REMOVED:
7034
0
      {
7035
0
        spinel_prop_key_t prop_key = SPINEL_PROP_LAST_STATUS;
7036
0
        const uint8_t *value_ptr = NULL;
7037
0
        spinel_size_t value_len = 0;
7038
0
        const char *prop_str;
7039
0
        bool skip_value_dump = false;
7040
0
        char value_dump_str[2 * kWPANTUND_SpinelPropValueDumpLen + 1];
7041
7042
0
        read_len = spinel_datatype_unpack(cmd_payload_ptr, cmd_payload_len, "iD", &prop_key, &value_ptr,
7043
0
          &value_len);
7044
0
        require_quiet(read_len > 0, bail);
7045
7046
0
        prop_str = spinel_prop_key_to_cstr(prop_key);
7047
7048
0
        switch (prop_key) {
7049
0
        case SPINEL_PROP_STREAM_DEBUG:           // Handled by `handle_ncp_debug_stream()`
7050
0
        case SPINEL_PROP_STREAM_LOG:             // Handled by `handle_ncp_log_stream()`
7051
0
        case SPINEL_PROP_STREAM_NET:             // Handled by `handle_normal_ipv6_from_ncp()
7052
0
        case SPINEL_PROP_STREAM_NET_INSECURE:    // Handled by `handle_normal_ipv6_from_ncp()
7053
          // Skip logging any of above properties
7054
0
          goto bail;
7055
7056
0
        case SPINEL_PROP_NET_MASTER_KEY:
7057
0
        case SPINEL_PROP_THREAD_ACTIVE_DATASET:
7058
0
        case SPINEL_PROP_THREAD_PENDING_DATASET:
7059
0
        case SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING:
7060
0
        case SPINEL_PROP_NET_PSKC:
7061
0
        case SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS:
7062
          // Hide the value by skipping value dump
7063
0
          skip_value_dump = true;
7064
0
          break;
7065
7066
0
        default:
7067
0
          skip_value_dump = false;
7068
0
          encode_data_into_string(value_ptr, value_len, value_dump_str, sizeof(value_dump_str), 0);
7069
0
          break;
7070
0
        }
7071
7072
0
        if (command == SPINEL_CMD_PROP_VALUE_GET) {
7073
0
          syslog(LOG_INFO, "%s (%d) %s(%s)", origin_str, tid, command_str, prop_str);
7074
0
        } else {
7075
0
          syslog(LOG_INFO, "%s (%d) %s(%s) [%s%s]", origin_str, tid, command_str, prop_str,
7076
0
            skip_value_dump ? "-- value hidden --" : value_dump_str,
7077
0
            skip_value_dump || (value_len <= kWPANTUND_SpinelPropValueDumpLen) ? "" : "...");
7078
0
        }
7079
0
      }
7080
0
      break;
7081
7082
0
    case SPINEL_CMD_PEEK:
7083
0
    case SPINEL_CMD_POKE:
7084
0
    case SPINEL_CMD_PEEK_RET:
7085
0
      {
7086
0
        uint32_t address = 0;
7087
0
        uint16_t count = 0;
7088
0
        read_len = spinel_datatype_unpack(cmd_payload_ptr, cmd_payload_len, "LS", &address, &count);
7089
0
        require_quiet(read_len > 0, bail);
7090
0
        syslog(LOG_INFO, "%s (%d) %s(0x%x, %d)", origin_str, tid, command_str, address, count);
7091
0
      }
7092
0
      break;
7093
7094
0
    default:
7095
0
      syslog(LOG_INFO, "%s (%d) %s(cmd_id:%d)", origin_str, tid, command_str, command);
7096
0
      break;
7097
0
    }
7098
0
  }
7099
7100
229k
bail:
7101
229k
  return;
7102
229k
}
7103
7104
bool
7105
SpinelNCPInstance::is_busy(void)
7106
3.03M
{
7107
3.03M
  return NCPInstanceBase::is_busy()
7108
205k
    || !mTaskQueue.empty();
7109
3.03M
}
7110
7111
void
7112
SpinelNCPInstance::process(void)
7113
2.90M
{
7114
2.90M
  NCPInstanceBase::process();
7115
7116
2.90M
  mVendorCustom.process();
7117
7118
2.90M
  if (!is_initializing_ncp() && mTaskQueue.empty()) {
7119
136k
    bool x = mPcapManager.is_enabled();
7120
7121
136k
    if (mIsPcapInProgress != x) {
7122
0
      SpinelNCPTaskSendCommand::Factory factory(this);
7123
7124
0
      mIsPcapInProgress = x;
7125
7126
0
      factory.add_command(SpinelPackData(
7127
0
        SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
7128
0
        SPINEL_PROP_MAC_RAW_STREAM_ENABLED,
7129
0
        mIsPcapInProgress
7130
0
      ));
7131
7132
0
      if (mIsPcapInProgress) {
7133
0
        factory.add_command(SpinelPackData(
7134
0
          SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
7135
0
          SPINEL_PROP_NET_IF_UP,
7136
0
          true
7137
0
        ));
7138
0
        if (!ncp_state_is_joining_or_joined(get_ncp_state())) {
7139
0
          factory.add_command(SpinelPackData(
7140
0
            SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S),
7141
0
            SPINEL_PROP_MAC_PROMISCUOUS_MODE,
7142
0
            SPINEL_MAC_PROMISCUOUS_MODE_FULL
7143
0
          ));
7144
0
        }
7145
0
      } else {
7146
0
        factory.add_command(SpinelPackData(
7147
0
          SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S),
7148
0
          SPINEL_PROP_MAC_PROMISCUOUS_MODE,
7149
0
          SPINEL_MAC_PROMISCUOUS_MODE_OFF
7150
0
        ));
7151
0
      }
7152
7153
0
      start_new_task(factory.finish());
7154
0
      NCPInstanceBase::process();
7155
0
    }
7156
136k
  }
7157
2.90M
}