diff --git a/doc/spinel-protocol-src/spinel-prop-net.md b/doc/spinel-protocol-src/spinel-prop-net.md index 4232aedd4..709810a16 100644 --- a/doc/spinel-protocol-src/spinel-prop-net.md +++ b/doc/spinel-protocol-src/spinel-prop-net.md @@ -55,8 +55,16 @@ Values: The partition ID of the partition that this node is a member of. -### PROP 73: PROP_NET_KEY_SWITCH_GUARDTIME {#prop-net-key-swtich-guardtime} +### PROP 73: PROP_NET_REQUIRE_JOIN_EXISTING {#prop-net-require-join-existing} +* Type: Read-Write +* Packed-Encoding: `b` + +### PROP 74: PROP_NET_KEY_SWITCH_GUARDTIME {#prop-net-key-swtich-guardtime} * Type: Read-Write * Packed-Encoding: `L` +### PROP 75: PROP_NET_PSKC {#prop-net-pskc} +* Type: Read-Write +* Packed-Encoding: `D` + diff --git a/examples/drivers/windows/include/otLwfIoctl.h b/examples/drivers/windows/include/otLwfIoctl.h index 3a51dbe35..eed57ae9f 100644 --- a/examples/drivers/windows/include/otLwfIoctl.h +++ b/examples/drivers/windows/include/otLwfIoctl.h @@ -689,8 +689,13 @@ typedef struct otCommissionConfig // GUID - InterfaceGuid // uint8_t - aRouterId +#define IOCTL_OTLWF_OT_PSKC \ + OTLWF_CTL_CODE(195, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) + // GUID - InterfaceGuid + // otPSKc - aPSKc + // OpenThread function IOCTL codes #define MIN_OTLWF_IOCTL_FUNC_CODE 100 -#define MAX_OTLWF_IOCTL_FUNC_CODE 194 +#define MAX_OTLWF_IOCTL_FUNC_CODE 195 #endif //__OTLWFIOCTL_H__ diff --git a/examples/drivers/windows/otApi/otApi.cpp b/examples/drivers/windows/otApi/otApi.cpp index fa176116a..7a0b10d31 100644 --- a/examples/drivers/windows/otApi/otApi.cpp +++ b/examples/drivers/windows/otApi/otApi.cpp @@ -1646,6 +1646,42 @@ otThreadSetMasterKey( return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_MASTER_KEY, Buffer, sizeof(Buffer), nullptr, 0)); } +OTAPI +const uint8_t * +OTCALL +otThreadGetPSKc( + _In_ otInstance *aInstance + ) +{ + if (aInstance == nullptr) return nullptr; + + uint8_t *Result = (uint8_t*)malloc(sizeof(otPSKc)); + if (Result == nullptr) return nullptr; + if (QueryIOCTL(aInstance, IOCTL_OTLWF_OT_PSKC, Result) != ERROR_SUCCESS) + { + free(Result); + return nullptr; + } + return Result; +} + +OTAPI +ThreadError +OTCALL +otThreadSetPSKc( + _In_ otInstance *aInstance, + const uint8_t *aPSKc + ) +{ + if (aInstance == nullptr) return kThreadError_InvalidArgs; + + BYTE Buffer[sizeof(GUID) + sizeof(otPSKc)]; + memcpy_s(Buffer, sizeof(Buffer), &aInstance->InterfaceGuid, sizeof(GUID)); + memcpy_s(Buffer + sizeof(GUID), sizeof(Buffer) - sizeof(GUID), aPSKc, sizeof(otPSKc)); + + return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_PSKC, Buffer, sizeof(Buffer), nullptr, 0)); +} + OTAPI int8_t OTCALL diff --git a/examples/drivers/windows/otLwf/iocontrol.c b/examples/drivers/windows/otLwf/iocontrol.c index 9b7c9c6fa..7011b4c4e 100644 --- a/examples/drivers/windows/otLwf/iocontrol.c +++ b/examples/drivers/windows/otLwf/iocontrol.c @@ -140,6 +140,7 @@ OTLWF_IOCTL_HANDLER IoCtls[] = { "IOCTL_OTLWF_OT_FACTORY_RESET", REF_IOCTL_FUNC(otFactoryReset) }, { "IOCTL_OTLWF_OT_THREAD_AUTO_START", REF_IOCTL_FUNC(otThreadAutoStart) }, { "IOCTL_OTLWF_OT_PREFERRED_ROUTER_ID", REF_IOCTL_FUNC(otThreadPreferredRouterId) }, + { "IOCTL_OTLWF_OT_PSKC", REF_IOCTL_FUNC_WITH_TUN(otPSKc) }, }; static_assert(ARRAYSIZE(IoCtls) == (MAX_OTLWF_IOCTL_FUNC_CODE - MIN_OTLWF_IOCTL_FUNC_CODE) + 1, @@ -1725,6 +1726,110 @@ otLwfTunIoCtl_otMasterKey_Handler( return status; } +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +otLwfIoCtl_otPSKc( + _In_ PMS_FILTER pFilter, + _In_reads_bytes_(InBufferLength) + PUCHAR InBuffer, + _In_ ULONG InBufferLength, + _Out_writes_bytes_(*OutBufferLength) + PVOID OutBuffer, + _Inout_ PULONG OutBufferLength + ) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + + if (InBufferLength >= sizeof(otPSKc)) + { + status = ThreadErrorToNtstatus(otThreadSetPSKc(pFilter->otCtx, InBuffer)); + *OutBufferLength = 0; + } + else if (*OutBufferLength >= sizeof(otPSKc)) + { + const uint8_t* aPSKc = otThreadGetPSKc(pFilter->otCtx); + memcpy(OutBuffer, aPSKc, sizeof(otPSKc)); + *OutBufferLength = sizeof(otPSKc); + status = STATUS_SUCCESS; + } + else + { + *OutBufferLength = 0; + } + + return status; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +otLwfTunIoCtl_otPSKc( + _In_ PMS_FILTER pFilter, + _In_ PIRP pIrp, + _In_reads_bytes_(InBufferLength) + PUCHAR InBuffer, + _In_ ULONG InBufferLength, + _In_ ULONG OutBufferLength + ) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + + if (InBufferLength >= sizeof(otPSKc)) + { + status = + otLwfTunSendCommandForIrp( + pFilter, + pIrp, + NULL, + SPINEL_CMD_PROP_VALUE_SET, + SPINEL_PROP_NET_PSKC, + sizeof(otPSKc) + sizeof(uint16_t), + SPINEL_DATATYPE_DATA_S, + (otPSKc*)InBuffer, + OT_PSKC_MAX_SIZE); + } + else if (OutBufferLength >= sizeof(otPSKc)) + { + status = + otLwfTunSendCommandForIrp( + pFilter, + pIrp, + otLwfTunIoCtl_otPSKc_Handler, + SPINEL_CMD_PROP_VALUE_GET, + SPINEL_PROP_NET_PSKC, + 0, + NULL); + } + + return status; +} + +_IRQL_requires_max_(DISPATCH_LEVEL) +NTSTATUS +otLwfTunIoCtl_otPSKc_Handler( + _In_ spinel_prop_key_t Key, + _In_reads_bytes_(DataLength) const uint8_t* Data, + _In_ spinel_size_t DataLength, + _Out_writes_bytes_(*OutBufferLength) + PVOID OutBuffer, + _Inout_ PULONG OutBufferLength + ) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + if (Key == SPINEL_PROP_NET_PSKC) + { + uint8_t *data = NULL; + spinel_size_t aPSKcLength; + if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_DATA_S, &data, &aPSKcLength) && data != NULL && + aPSKcLength == sizeof(otPSKc)) + { + memcpy(OutBuffer, data, sizeof(otPSKc)); + *OutBufferLength = sizeof(otPSKc); + status = STATUS_SUCCESS; + } + } + return status; +} + _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS otLwfIoCtl_otMeshLocalEid( diff --git a/examples/drivers/windows/otLwf/iocontrol.h b/examples/drivers/windows/otLwf/iocontrol.h index 18b1022de..724c2caa7 100644 --- a/examples/drivers/windows/otLwf/iocontrol.h +++ b/examples/drivers/windows/otLwf/iocontrol.h @@ -226,5 +226,6 @@ DECL_IOCTL_FUNC_WITH_TUN2(otKeySwitchGuardtime); DECL_IOCTL_FUNC(otFactoryReset); DECL_IOCTL_FUNC(otThreadAutoStart); DECL_IOCTL_FUNC(otThreadPreferredRouterId); +DECL_IOCTL_FUNC_WITH_TUN2(otPSKc); #endif // _IOCONTROL_H diff --git a/examples/drivers/windows/otNodeApi/otNodeApi.cpp b/examples/drivers/windows/otNodeApi/otNodeApi.cpp index f34a1da34..ffaa80dca 100644 --- a/examples/drivers/windows/otNodeApi/otNodeApi.cpp +++ b/examples/drivers/windows/otNodeApi/otNodeApi.cpp @@ -1231,6 +1231,41 @@ OTNODEAPI const char* OTCALL otNodeGetMasterkey(otNode* aNode) return str; } +OTNODEAPI int32_t OTCALL otNodeSetPSKc(otNode* aNode, const char *aPSKc) +{ + otLogFuncEntryMsg("[%d] %s", aNode->mId, aPSKc); + printf("%d: pskc %s\r\n", aNode->mId, aPSKc); + + uint8_t pskc[OT_PSKC_MAX_SIZE]; + if (Hex2Bin(aPSKc, pskc, sizeof(pskc)) != OT_PSKC_MAX_SIZE) + { + printf("invalid pskc %s\r\n", aPSKc); + return kThreadError_Parse; + } + + auto error = otThreadSetPSKc(aNode->mInstance, pskc); + otLogFuncExit(); + return error; +} + +OTNODEAPI const char* OTCALL otNodeGetPSKc(otNode* aNode) +{ + otLogFuncEntryMsg("[%d]", aNode->mId); + auto aPSKc = otThreadGetPSKc(aNode->mInstance); + uint8_t strLength = 2 * OT_PSKC_MAX_SIZE + 1; + char* str = (char*)malloc(strLength); + if (str != nullptr) + { + aNode->mMemoryToFree.push_back(str); + for (int i = 0; i < OT_PSKC_MAX_SIZE; i++) + sprintf_s(str + i * 2, strLength - (2 * i), "%02x", aPSKc[i]); + printf("%d: pskc\r\n%s\r\n", aNode->mId, str); + } + otFreeMemory(aPSKc); + otLogFuncExit(); + return str; +} + OTNODEAPI uint32_t OTCALL otNodeGetKeySequenceCounter(otNode* aNode) { otLogFuncEntryMsg("[%d]", aNode->mId); diff --git a/include/openthread/thread.h b/include/openthread/thread.h index cb94a1a91..b79c04dde 100644 --- a/include/openthread/thread.h +++ b/include/openthread/thread.h @@ -288,6 +288,34 @@ OTAPI const uint8_t *OTCALL otThreadGetMasterKey(otInstance *aInstance, uint8_t */ OTAPI ThreadError OTCALL otThreadSetMasterKey(otInstance *aInstance, const uint8_t *aKey, uint8_t aKeyLength); +/** + * Get the thrPSKc. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns A pointer to a buffer containing the thrPSKc. + * + * @sa otThreadSetPSKc + */ +OTAPI const uint8_t *OTCALL otThreadGetPSKc(otInstance *aInstance); + +/** + * Set the thrPSKc. + * + * This function will only succeed when Thread protocols are disabled. A successful + * call to this function will also invalidate the Active and Pending Operational Datasets in + * non-volatile memory. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aPSKc A pointer to a buffer containing the thrPSKc. + * + * @retval kThreadError_None Successfully set the thrPSKc. + * @retval kThreadError_InvalidState Thread protocols are enabled. + * + * @sa otThreadGetPSKc + */ +OTAPI ThreadError OTCALL otThreadSetPSKc(otInstance *aInstance, const uint8_t *aPSKc); + /** * This function returns a pointer to the Mesh Local EID. * diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index e5528866f..8b456da28 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -156,6 +156,9 @@ const struct Command Interpreter::sCommands[] = { "promiscuous", &Interpreter::ProcessPromiscuous }, #endif { "prefix", &Interpreter::ProcessPrefix }, +#if OPENTHREAD_FTD + { "pskc", &Interpreter::ProcessPSKc }, +#endif { "releaserouterid", &Interpreter::ProcessReleaseRouterId }, { "reset", &Interpreter::ProcessReset }, { "rloc16", &Interpreter::ProcessRloc16 }, @@ -1292,6 +1295,35 @@ exit: AppendResult(error); } +#if OPENTHREAD_FTD +void Interpreter::ProcessPSKc(int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + + if (argc == 0) + { + const uint8_t *currentPSKc = otThreadGetPSKc(mInstance); + + for (int i = 0; i < OT_PSKC_MAX_SIZE; i++) + { + sServer->OutputFormat("%02x", currentPSKc[i]); + } + + sServer->OutputFormat("\r\n"); + } + else + { + uint8_t newPSKc[OT_PSKC_MAX_SIZE]; + + VerifyOrExit(Hex2Bin(argv[0], newPSKc, sizeof(newPSKc)) == OT_PSKC_MAX_SIZE, error = kThreadError_Parse); + SuccessOrExit(error = otThreadSetPSKc(mInstance, newPSKc)); + } + +exit: + AppendResult(error); +} +#endif + void Interpreter::ProcessMasterKey(int argc, char *argv[]) { ThreadError error = kThreadError_None; diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 2a8acc270..10ceabb2a 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -226,6 +226,9 @@ private: ThreadError ProcessPrefixRemove(int argc, char *argv[]); ThreadError ProcessPrefixList(void); void ProcessPromiscuous(int argc, char *argv[]); +#if OPENTHREAD_FTD + void ProcessPSKc(int argc, char *argv[]); +#endif void ProcessReleaseRouterId(int argc, char *argv[]); void ProcessReset(int argc, char *argv[]); void ProcessRoute(int argc, char *argv[]); diff --git a/src/core/api/thread_api.cpp b/src/core/api/thread_api.cpp index 931051186..0910c6a21 100644 --- a/src/core/api/thread_api.cpp +++ b/src/core/api/thread_api.cpp @@ -163,6 +163,27 @@ ThreadError otThreadSetLinkMode(otInstance *aInstance, otLinkModeConfig aConfig) return aInstance->mThreadNetif.GetMle().SetDeviceMode(mode); } +#if OPENTHREAD_FTD +const uint8_t *otThreadGetPSKc(otInstance *aInstance) +{ + return aInstance->mThreadNetif.GetKeyManager().GetPSKc(); +} + +ThreadError otThreadSetPSKc(otInstance *aInstance, const uint8_t *aPSKc) +{ + ThreadError error = kThreadError_None; + VerifyOrExit(aInstance->mThreadNetif.GetMle().GetDeviceState() == Mle::kDeviceStateDisabled, + error = kThreadError_InvalidState); + + aInstance->mThreadNetif.GetKeyManager().SetPSKc(aPSKc); + aInstance->mThreadNetif.GetActiveDataset().Clear(false); + aInstance->mThreadNetif.GetPendingDataset().Clear(false); + +exit: + return error; +} +#endif + const uint8_t *otThreadGetMasterKey(otInstance *aInstance, uint8_t *aKeyLength) { return aInstance->mThreadNetif.GetKeyManager().GetMasterKey(aKeyLength); diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp index 3b0723c4d..2d89979f6 100644 --- a/src/core/meshcop/dataset_manager.cpp +++ b/src/core/meshcop/dataset_manager.cpp @@ -135,6 +135,17 @@ ThreadError DatasetManager::ApplyConfiguration(void) break; } +#if OPENTHREAD_FTD + + case Tlv::kPSKc: + { + const PSKcTlv *pskc = static_cast(cur); + mNetif.GetKeyManager().SetPSKc(pskc->GetPSKc()); + break; + } + +#endif + case Tlv::kMeshLocalPrefix: { const MeshLocalPrefixTlv *prefix = static_cast(cur); diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp index d2d4e17a8..00aa19e7e 100644 --- a/src/core/meshcop/dataset_manager_ftd.cpp +++ b/src/core/meshcop/dataset_manager_ftd.cpp @@ -162,10 +162,9 @@ ThreadError ActiveDataset::GenerateLocal(void) // PSKc if (!IsTlvInitialized(Tlv::kPSKc)) { - const uint8_t pskc[OT_PSKC_MAX_SIZE] = {0}; PSKcTlv tlv; tlv.Init(); - tlv.SetPSKc(pskc); + tlv.SetPSKc(mNetif.GetKeyManager().GetPSKc()); mLocal.Set(tlv); } diff --git a/src/core/thread/key_manager.cpp b/src/core/thread/key_manager.cpp index 6eff30a8f..c2c7aa250 100644 --- a/src/core/thread/key_manager.cpp +++ b/src/core/thread/key_manager.cpp @@ -80,6 +80,18 @@ void KeyManager::Stop(void) mKeyRotationTimer.Stop(); } +#if OPENTHREAD_FTD +const uint8_t *KeyManager::GetPSKc(void) const +{ + return mPSKc; +} + +void KeyManager::SetPSKc(const uint8_t *aPSKc) +{ + memcpy(mPSKc, aPSKc, sizeof(mPSKc)); +} +#endif + const uint8_t *KeyManager::GetMasterKey(uint8_t *aKeyLength) const { if (aKeyLength) diff --git a/src/core/thread/key_manager.hpp b/src/core/thread/key_manager.hpp index a03779aa7..64269ef5f 100644 --- a/src/core/thread/key_manager.hpp +++ b/src/core/thread/key_manager.hpp @@ -104,6 +104,22 @@ public: */ ThreadError SetMasterKey(const void *aKey, uint8_t aKeyLength); + /** + * This method returns a pointer to the PSKc. + * + * @returns A pointer to the PSKc. + * + */ + const uint8_t *GetPSKc(void) const; + + /** + * This method sets the PSKc. + * + * @param[in] aPSKc A pointer to the PSKc. + * + */ + void SetPSKc(const uint8_t *aPSKc); + /** * This method returns the current key sequence value. * @@ -346,6 +362,9 @@ private: bool mKeySwitchGuardEnabled; Timer mKeyRotationTimer; +#if OPENTHREAD_FTD + uint8_t mPSKc[kMaxKeyLength]; +#endif uint8_t mKek[kMaxKeyLength]; uint32_t mKekFrameCounter; diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 381dbe56c..ec047abcd 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -141,6 +141,9 @@ const NcpBase::GetPropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] = { SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER, &NcpBase::GetPropertyHandler_NET_KEY_SEQUENCE_COUNTER }, { SPINEL_PROP_NET_PARTITION_ID, &NcpBase::GetPropertyHandler_NET_PARTITION_ID }, { SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME, &NcpBase::GetPropertyHandler_NET_KEY_SWITCH_GUARDTIME}, +#if OPENTHREAD_FTD + { SPINEL_PROP_NET_PSKC, &NcpBase::GetPropertyHandler_NET_PSKC }, +#endif { SPINEL_PROP_THREAD_LEADER_ADDR, &NcpBase::GetPropertyHandler_THREAD_LEADER_ADDR }, { SPINEL_PROP_THREAD_PARENT, &NcpBase::GetPropertyHandler_THREAD_PARENT }, @@ -280,6 +283,9 @@ const NcpBase::SetPropertyHandlerEntry NcpBase::mSetPropertyHandlerTable[] = { SPINEL_PROP_NET_MASTER_KEY, &NcpBase::SetPropertyHandler_NET_MASTER_KEY }, { SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER, &NcpBase::SetPropertyHandler_NET_KEY_SEQUENCE_COUNTER }, { SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME, &NcpBase::SetPropertyHandler_NET_KEY_SWITCH_GUARDTIME}, +#if OPENTHREAD_FTD + { SPINEL_PROP_NET_PSKC, &NcpBase::SetPropertyHandler_NET_PSKC }, +#endif { SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT, &NcpBase::SetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT }, { SPINEL_PROP_THREAD_ASSISTING_PORTS, &NcpBase::SetPropertyHandler_THREAD_ASSISTING_PORTS }, @@ -3336,6 +3342,20 @@ ThreadError NcpBase::GetPropertyHandler_MAC_WHITELIST_ENABLED(uint8_t header, sp ); } +#if OPENTHREAD_FTD +ThreadError NcpBase::GetPropertyHandler_NET_PSKC(uint8_t header, spinel_prop_key_t key) +{ + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_DATA_S, + otThreadGetPSKc(mInstance), + sizeof(spinel_net_pskc_t) + ); +} +#endif // OPENTHREAD_FTD + ThreadError NcpBase::GetPropertyHandler_THREAD_MODE(uint8_t header, spinel_prop_key_t key) { uint8_t numeric_mode(0); @@ -5275,6 +5295,45 @@ exit: #endif +#if OPENTHREAD_FTD +ThreadError NcpBase::SetPropertyHandler_NET_PSKC(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len) +{ + const uint8_t *ptr = NULL; + spinel_size_t len; + spinel_ssize_t parsedLength; + ThreadError errorCode = kThreadError_None; + + parsedLength = spinel_datatype_unpack( + value_ptr, + value_len, + SPINEL_DATATYPE_DATA_S, + &ptr, + &len + ); + + if ((parsedLength > 0) && (len == sizeof(spinel_net_pskc_t))) + { + errorCode = otThreadSetPSKc(mInstance, ptr); + if (errorCode == kThreadError_None) + { + errorCode = HandleCommandPropertyGet(header, key); + } + + if (errorCode) + { + errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode)); + } + } + else + { + errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR); + } + + return errorCode; +} +#endif // OPENTHREAD_FTD + ThreadError NcpBase::SetPropertyHandler_THREAD_MODE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len) { diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 6a898e0cc..fd1cd7a0a 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -393,6 +393,9 @@ private: ThreadError GetPropertyHandler_MAC_WHITELIST(uint8_t header, spinel_prop_key_t key); ThreadError GetPropertyHandler_MAC_WHITELIST_ENABLED(uint8_t header, spinel_prop_key_t key); ThreadError GetPropertyHandler_THREAD_MODE(uint8_t header, spinel_prop_key_t key); +#if OPENTHREAD_FTD + ThreadError GetPropertyHandler_NET_PSKC(uint8_t header, spinel_prop_key_t key); +#endif ThreadError GetPropertyHandler_THREAD_CHILD_COUNT_MAX(uint8_t header, spinel_prop_key_t key); ThreadError GetPropertyHandler_THREAD_CHILD_TIMEOUT(uint8_t header, spinel_prop_key_t key); ThreadError GetPropertyHandler_THREAD_RLOC16(uint8_t header, spinel_prop_key_t key); @@ -500,6 +503,10 @@ private: const uint8_t *value_ptr, uint16_t value_len); ThreadError SetPropertyHandler_MAC_SRC_MATCH_EXTENDED_ADDRESSES(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); +#endif +#if OPENTHREAD_FTD + ThreadError SetPropertyHandler_NET_PSKC(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, + uint16_t value_len); #endif ThreadError SetPropertyHandler_THREAD_MODE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); diff --git a/src/ncp/spinel.c b/src/ncp/spinel.c index 93276ba66..d39231b70 100644 --- a/src/ncp/spinel.c +++ b/src/ncp/spinel.c @@ -1068,6 +1068,10 @@ spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "PROP_NET_KEY_SWITCH_GUARDTIME"; break; + case SPINEL_PROP_NET_PSKC: + ret = "PROP_NET_PSKC"; + break; + case SPINEL_PROP_THREAD_LEADER_ADDR: ret = "PROP_THREAD_LEADER_ADDR"; break; diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index ee415b9ca..ac4a29e9e 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -251,6 +251,11 @@ typedef struct uint8_t bytes[8]; } spinel_net_xpanid_t; +typedef struct +{ + uint8_t bytes[16]; +} spinel_net_pskc_t; + typedef struct { uint8_t bytes[6]; @@ -688,6 +693,8 @@ typedef enum SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME = SPINEL_PROP_NET__BEGIN + 10, ///< [L] + SPINEL_PROP_NET_PSKC = SPINEL_PROP_NET__BEGIN + 11, ///< [D] + SPINEL_PROP_NET__END = 0x50, SPINEL_PROP_THREAD__BEGIN = 0x50,