diff --git a/Android.mk b/Android.mk index d32e86b5f..4d09fcc91 100644 --- a/Android.mk +++ b/Android.mk @@ -286,6 +286,7 @@ LOCAL_SRC_FILES := \ src/core/meshcop/meshcop.cpp \ src/core/meshcop/meshcop_leader.cpp \ src/core/meshcop/meshcop_tlvs.cpp \ + src/core/meshcop/network_name.cpp \ src/core/meshcop/panid_query_client.cpp \ src/core/meshcop/timestamp.cpp \ src/core/net/checksum.cpp \ diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 66075c74b..1518546d5 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -521,6 +521,8 @@ openthread_core_files = [ "meshcop/meshcop_leader.hpp", "meshcop/meshcop_tlvs.cpp", "meshcop/meshcop_tlvs.hpp", + "meshcop/network_name.cpp", + "meshcop/network_name.hpp", "meshcop/panid_query_client.cpp", "meshcop/panid_query_client.hpp", "meshcop/timestamp.cpp", diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5d2251148..e09f7e5f2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -152,6 +152,7 @@ set(COMMON_SOURCES meshcop/meshcop.cpp meshcop/meshcop_leader.cpp meshcop/meshcop_tlvs.cpp + meshcop/network_name.cpp meshcop/panid_query_client.cpp meshcop/timestamp.cpp net/checksum.cpp diff --git a/src/core/Makefile.am b/src/core/Makefile.am index cfeeae7ca..850228d49 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -242,6 +242,7 @@ SOURCES_COMMON = \ meshcop/meshcop.cpp \ meshcop/meshcop_leader.cpp \ meshcop/meshcop_tlvs.cpp \ + meshcop/network_name.cpp \ meshcop/panid_query_client.cpp \ meshcop/timestamp.cpp \ net/checksum.cpp \ @@ -543,6 +544,7 @@ HEADERS_COMMON = \ meshcop/meshcop.hpp \ meshcop/meshcop_leader.hpp \ meshcop/meshcop_tlvs.hpp \ + meshcop/network_name.hpp \ meshcop/panid_query_client.hpp \ meshcop/timestamp.hpp \ net/checksum.hpp \ diff --git a/src/core/api/thread_api.cpp b/src/core/api/thread_api.cpp index cd440dc87..7b7275720 100644 --- a/src/core/api/thread_api.cpp +++ b/src/core/api/thread_api.cpp @@ -200,7 +200,7 @@ otError otThreadGetServiceAloc(otInstance *aInstance, uint8_t aServiceId, otIp6A const char *otThreadGetNetworkName(otInstance *aInstance) { - return AsCoreType(aInstance).Get().GetNetworkName().GetAsCString(); + return AsCoreType(aInstance).Get().GetNetworkName().GetAsCString(); } otError otThreadSetNetworkName(otInstance *aInstance, const char *aNetworkName) @@ -209,7 +209,7 @@ otError otThreadSetNetworkName(otInstance *aInstance, const char *aNetworkName) VerifyOrExit(AsCoreType(aInstance).Get().IsDisabled(), error = kErrorInvalidState); - error = AsCoreType(aInstance).Get().SetNetworkName(aNetworkName); + error = AsCoreType(aInstance).Get().SetNetworkName(aNetworkName); AsCoreType(aInstance).Get().Clear(); AsCoreType(aInstance).Get().Clear(); @@ -220,7 +220,7 @@ exit: #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) const char *otThreadGetDomainName(otInstance *aInstance) { - return AsCoreType(aInstance).Get().GetDomainName().GetAsCString(); + return AsCoreType(aInstance).Get().GetDomainName().GetAsCString(); } otError otThreadSetDomainName(otInstance *aInstance, const char *aDomainName) @@ -229,7 +229,7 @@ otError otThreadSetDomainName(otInstance *aInstance, const char *aDomainName) VerifyOrExit(AsCoreType(aInstance).Get().IsDisabled(), error = kErrorInvalidState); - error = AsCoreType(aInstance).Get().SetDomainName(aDomainName); + error = AsCoreType(aInstance).Get().SetDomainName(aDomainName); exit: return error; diff --git a/src/core/backbone_router/bbr_manager.cpp b/src/core/backbone_router/bbr_manager.cpp index d67793550..2d29a6f65 100644 --- a/src/core/backbone_router/bbr_manager.cpp +++ b/src/core/backbone_router/bbr_manager.cpp @@ -687,7 +687,7 @@ Error Manager::SendBackboneAnswer(const Ip6::Address & aDstAddr, SuccessOrExit(error = Tlv::Append(*message, aTimeSinceLastTransaction)); { - const Mac::NameData nameData = Get().GetNetworkName().GetAsData(); + const MeshCoP::NameData nameData = Get().GetNetworkName().GetAsData(); SuccessOrExit(error = Tlv::Append(*message, nameData.GetBuffer(), nameData.GetLength())); } diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index f71230d0a..c1bf4b1ad 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -72,6 +72,7 @@ #include "meshcop/border_agent.hpp" #include "meshcop/dataset_updater.hpp" #include "meshcop/extended_panid.hpp" +#include "meshcop/network_name.hpp" #include "net/ip6.hpp" #include "thread/announce_sender.hpp" #include "thread/link_metrics.hpp" @@ -707,6 +708,11 @@ template <> inline MeshCoP::ExtendedPanIdManager &Instance::Get(void) return mThreadNetif.mExtendedPanIdManager; } +template <> inline MeshCoP::NetworkNameManager &Instance::Get(void) +{ + return mThreadNetif.mNetworkNameManager; +} + template <> inline MeshCoP::ActiveDataset &Instance::Get(void) { return mThreadNetif.mActiveDataset; diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 054a50a31..7e2f6503c 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -63,12 +63,6 @@ const otExtAddress Mac::sMode2ExtAddress = { {0x35, 0x06, 0xfe, 0xb8, 0x23, 0xd4, 0x87, 0x12}, }; -const char Mac::sNetworkNameInit[] = "OpenThread"; - -#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) -const char Mac::sDomainNameInit[] = "DefaultDomain"; -#endif - Mac::Mac(Instance &aInstance) : InstanceLocator(aInstance) , mEnabled(false) @@ -124,10 +118,6 @@ Mac::Mac(Instance &aInstance) mLinks.Enable(); Get().UpdateKeyMaterial(); - IgnoreError(SetNetworkName(sNetworkNameInit)); -#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) - IgnoreError(SetDomainName(sDomainNameInit)); -#endif SetPanId(mPanId); SetExtAddress(randomExtAddress); SetShortAddress(GetShortAddress()); @@ -440,52 +430,6 @@ void Mac::SetSupportedChannelMask(const ChannelMask &aMask) IgnoreError(Get().Update(mSupportedChannelMask, newMask, kEventSupportedChannelMaskChanged)); } -Error Mac::SetNetworkName(const char *aNameString) -{ - return SignalNetworkNameChange(mNetworkName.Set(aNameString)); -} - -Error Mac::SetNetworkName(const NameData &aNameData) -{ - return SignalNetworkNameChange(mNetworkName.Set(aNameData)); -} - -Error Mac::SignalNetworkNameChange(Error aError) -{ - switch (aError) - { - case kErrorNone: - Get().Signal(kEventThreadNetworkNameChanged); - break; - - case kErrorAlready: - Get().SignalIfFirst(kEventThreadNetworkNameChanged); - aError = kErrorNone; - break; - - default: - break; - } - - return aError; -} - -#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) -Error Mac::SetDomainName(const char *aNameString) -{ - Error error = mDomainName.Set(aNameString); - - return (error == kErrorAlready) ? kErrorNone : error; -} - -Error Mac::SetDomainName(const NameData &aNameData) -{ - Error error = mDomainName.Set(aNameData); - - return (error == kErrorAlready) ? kErrorNone : error; -} -#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) - void Mac::SetPanId(PanId aPanId) { SuccessOrExit(Get().Update(mPanId, aPanId, kEventThreadPanIdChanged)); diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index 6a5ed7fd4..a5929a6d1 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -323,68 +323,6 @@ public: */ void SetSupportedChannelMask(const ChannelMask &aMask); - /** - * This method returns the IEEE 802.15.4 Network Name. - * - * @returns The IEEE 802.15.4 Network Name. - * - */ - const NetworkName &GetNetworkName(void) const { return mNetworkName; } - - /** - * This method sets the IEEE 802.15.4 Network Name. - * - * @param[in] aNameString A pointer to a string character array. Must be null terminated. - * - * @retval kErrorNone Successfully set the IEEE 802.15.4 Network Name. - * @retval kErrorInvalidArgs Given name is too long. - * - */ - Error SetNetworkName(const char *aNameString); - - /** - * This method sets the IEEE 802.15.4 Network Name. - * - * @param[in] aNameData A name data (pointer to char buffer and length). - * - * @retval kErrorNone Successfully set the IEEE 802.15.4 Network Name. - * @retval kErrorInvalidArgs Given name is too long. - * - */ - Error SetNetworkName(const NameData &aNameData); - -#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) - /** - * This method returns the Thread Domain Name. - * - * @returns The Thread Domain Name. - * - */ - const DomainName &GetDomainName(void) const { return mDomainName; } - - /** - * This method sets the Thread Domain Name. - * - * @param[in] aNameString A pointer to a string character array. Must be null terminated. - * - * @retval kErrorNone Successfully set the Thread Domain Name. - * @retval kErrorInvalidArgs Given name is too long. - * - */ - Error SetDomainName(const char *aNameString); - - /** - * This method sets the Thread Domain Name. - * - * @param[in] aNameData A name data (pointer to char buffer and length). - * - * @retval kErrorNone Successfully set the Thread Domain Name. - * @retval kErrorInvalidArgs Given name is too long. - * - */ - Error SetDomainName(const NameData &aNameData); -#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) - /** * This method returns the IEEE 802.15.4 PAN ID. * @@ -836,7 +774,6 @@ private: Error ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult); void PerformEnergyScan(void); void ReportEnergyScanResult(int8_t aRssi); - Error SignalNetworkNameChange(Error aError); void LogFrameRxFailure(const RxFrame *aFrame, Error aError) const; void LogFrameTxFailure(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx) const; @@ -855,8 +792,6 @@ private: static const char *OperationToString(Operation aOperation); static const otExtAddress sMode2ExtAddress; - static const char sNetworkNameInit[]; - static const char sDomainNameInit[]; bool mEnabled : 1; bool mShouldTxPollBeforeData : 1; @@ -877,10 +812,6 @@ private: uint8_t mPanChannel; uint8_t mRadioChannel; ChannelMask mSupportedChannelMask; - NetworkName mNetworkName; -#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) - DomainName mDomainName; -#endif uint8_t mScanChannel; uint16_t mScanDuration; ChannelMask mScanChannelMask; diff --git a/src/core/mac/mac_types.cpp b/src/core/mac/mac_types.cpp index a0d484781..83fab4ba9 100644 --- a/src/core/mac/mac_types.cpp +++ b/src/core/mac/mac_types.cpp @@ -110,71 +110,6 @@ Address::InfoString Address::ToString(void) const return string; } -uint8_t NameData::CopyTo(char *aBuffer, uint8_t aMaxSize) const -{ - MutableData destData; - - destData.Init(aBuffer, aMaxSize); - destData.ClearBytes(); - IgnoreError(destData.CopyBytesFrom(*this)); - - return destData.GetLength(); -} - -NameData NetworkName::GetAsData(void) const -{ - return NameData(m8, static_cast(StringLength(m8, kMaxSize + 1))); -} - -Error NetworkName::Set(const char *aNameString) -{ - // When setting `NetworkName` from a string, we treat it as `NameData` - // with `kMaxSize + 1` chars. `NetworkName::Set(data)` will look - // for null char in the data (within its given size) to calculate - // the name's length and ensure that the name fits in `kMaxSize` - // chars. The `+ 1` ensures that a `aNameString` with length - // longer than `kMaxSize` is correctly rejected (returning error - // `kErrorInvalidArgs`). - - Error error; - NameData data(aNameString, kMaxSize + 1); - - VerifyOrExit(IsValidUtf8String(aNameString), error = kErrorInvalidArgs); - - error = Set(data); - -exit: - return error; -} - -Error NetworkName::Set(const NameData &aNameData) -{ - Error error = kErrorNone; - NameData data = aNameData; - uint8_t newLen = static_cast(StringLength(data.GetBuffer(), data.GetLength())); - - VerifyOrExit((0 < newLen) && (newLen <= kMaxSize), error = kErrorInvalidArgs); - - data.SetLength(newLen); - - // Ensure the new name does not match the current one. - if (data.MatchesBytesIn(m8) && m8[newLen] == '\0') - { - ExitNow(error = kErrorAlready); - } - - data.CopyBytesTo(m8); - m8[newLen] = '\0'; - -exit: - return error; -} - -bool NetworkName::operator==(const NetworkName &aOther) const -{ - return GetAsData() == aOther.GetAsData(); -} - #if OPENTHREAD_CONFIG_MULTI_RADIO const RadioType RadioTypes::kAllRadioTypes[kNumRadioTypes] = { diff --git a/src/core/mac/mac_types.hpp b/src/core/mac/mac_types.hpp index 3456521d8..483a5b976 100644 --- a/src/core/mac/mac_types.hpp +++ b/src/core/mac/mac_types.hpp @@ -552,139 +552,6 @@ private: void SetKey(const Key &aKey) { mKeyMaterial.mKey = aKey; } }; -/** - * This class represents a name string as data (pointer to a char buffer along with a length). - * - * @note The char array does NOT need to be null terminated. - * - */ -class NameData : private Data -{ - friend class NetworkName; - -public: - /** - * This constructor initializes the NameData object. - * - * @param[in] aBuffer A pointer to a `char` buffer (does not need to be null terminated). - * @param[in] aLength The length (number of chars) in the buffer. - * - */ - NameData(const char *aBuffer, uint8_t aLength) { Init(aBuffer, aLength); } - - /** - * This method returns the pointer to char buffer (not necessarily null terminated). - * - * @returns The pointer to the char buffer. - * - */ - const char *GetBuffer(void) const { return reinterpret_cast(GetBytes()); } - - /** - * This method returns the length (number of chars in buffer). - * - * @returns The name length. - * - */ - uint8_t GetLength(void) const { return Data::GetLength(); } - - /** - * This method copies the name data into a given char buffer with a given size. - * - * The given buffer is cleared (`memset` to zero) before copying the name into it. The copied string - * in @p aBuffer is NOT necessarily null terminated. - * - * @param[out] aBuffer A pointer to a buffer where to copy the name into. - * @param[in] aMaxSize Size of @p aBuffer (maximum number of chars to write into @p aBuffer). - * - * @returns The actual number of chars copied into @p aBuffer. - * - */ - uint8_t CopyTo(char *aBuffer, uint8_t aMaxSize) const; -}; - -/** - * This structure represents an IEEE802.15.4 Network Name. - * - */ -class NetworkName : public otNetworkName, public Unequatable -{ -public: - /** - * This constant specified the maximum number of chars in Network Name (excludes null char). - * - */ - static constexpr uint8_t kMaxSize = OT_NETWORK_NAME_MAX_SIZE; - - /** - * This constructor initializes the IEEE802.15.4 Network Name as an empty string. - * - */ - NetworkName(void) { m8[0] = '\0'; } - - /** - * This method gets the IEEE802.15.4 Network Name as a null terminated C string. - * - * @returns The Network Name as a null terminated C string array. - * - */ - const char *GetAsCString(void) const { return m8; } - - /** - * This method gets the IEEE802.15.4 Network Name as NameData. - * - * @returns The Network Name as NameData. - * - */ - NameData GetAsData(void) const; - - /** - * This method sets the IEEE 802.15.4 Network Name from a given null terminated C string. - * - * This method also validates that the given @p aNameString follows UTF-8 encoding and can fit in `kMaxSize` - * chars. - * - * @param[in] aNameString A name C string. - * - * @retval kErrorNone Successfully set the IEEE 802.15.4 Network Name. - * @retval kErrorAlready The name is already set to the same string. - * @retval kErrorInvalidArgs Given name is invalid (too long or does not follow UTF-8 encoding). - * - */ - Error Set(const char *aNameString); - - /** - * This method sets the IEEE 802.15.4 Network Name. - * - * @param[in] aNameData A reference to name data. - * - * @retval kErrorNone Successfully set the IEEE 802.15.4 Network Name. - * @retval kErrorAlready The name is already set to the same string. - * @retval kErrorInvalidArgs Given name is too long. - * - */ - Error Set(const NameData &aNameData); - - /** - * This method overloads operator `==` to evaluate whether or not two given `NetworkName` objects are equal. - * - * @param[in] aOther The other `NetworkName` to compare with. - * - * @retval TRUE If the two are equal. - * @retval FALSE If the two are not equal. - * - */ - bool operator==(const NetworkName &aOther) const; -}; - -#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) -/** - * This type represents a Thread Domain Name. - * - */ -typedef NetworkName DomainName; -#endif - #if OPENTHREAD_CONFIG_MULTI_RADIO /** @@ -998,7 +865,6 @@ private: DefineCoreType(otExtAddress, Mac::ExtAddress); DefineCoreType(otMacKey, Mac::Key); -DefineCoreType(otNetworkName, Mac::NetworkName); } // namespace ot diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp index 4280d65d6..ad6adec48 100644 --- a/src/core/meshcop/dataset.cpp +++ b/src/core/meshcop/dataset.cpp @@ -340,7 +340,7 @@ Error Dataset::SetFrom(const Info &aDatasetInfo) if (aDatasetInfo.IsNetworkNamePresent()) { - Mac::NameData nameData = aDatasetInfo.GetNetworkName().GetAsData(); + NameData nameData = aDatasetInfo.GetNetworkName().GetAsData(); IgnoreError(SetTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength())); } @@ -559,7 +559,8 @@ Error Dataset::ApplyConfiguration(Instance &aInstance, bool *aIsNetworkKeyUpdate break; case Tlv::kNetworkName: - IgnoreError(mac.SetNetworkName(As(cur)->GetNetworkName())); + IgnoreError( + aInstance.Get().SetNetworkName(As(cur)->GetNetworkName())); break; case Tlv::kNetworkKey: diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp index c40aac559..36b08fe17 100644 --- a/src/core/meshcop/dataset.hpp +++ b/src/core/meshcop/dataset.hpp @@ -308,7 +308,7 @@ public: * @returns The Network Name in the Dataset. * */ - const Mac::NetworkName &GetNetworkName(void) const { return AsCoreType(&mNetworkName); } + const NetworkName &GetNetworkName(void) const { return AsCoreType(&mNetworkName); } /** * This method sets the Network Name in the Dataset. @@ -316,7 +316,7 @@ public: * @param[in] aNetworkNameData A Network Name Data. * */ - void SetNetworkName(const Mac::NameData &aNetworkNameData) + void SetNetworkName(const NameData &aNetworkNameData) { IgnoreError(AsCoreType(&mNetworkName).Set(aNetworkNameData)); mComponents.mIsNetworkNamePresent = true; diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp index 59d2b96e8..7893bcc30 100644 --- a/src/core/meshcop/dataset_manager_ftd.cpp +++ b/src/core/meshcop/dataset_manager_ftd.cpp @@ -352,7 +352,7 @@ Error ActiveDataset::GenerateLocal(void) if (dataset.GetTlv() == nullptr) { - Mac::NameData nameData = Get().GetNetworkName().GetAsData(); + MeshCoP::NameData nameData = Get().GetNetworkName().GetAsData(); IgnoreError(dataset.SetTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength())); } diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp index d817b1da5..48995b4ae 100644 --- a/src/core/meshcop/joiner_router.cpp +++ b/src/core/meshcop/joiner_router.cpp @@ -328,7 +328,7 @@ Coap::Message *JoinerRouter::PrepareJoinerEntrustMessage(void) SuccessOrExit(error = Tlv::Append(*message, Get().GetExtPanId())); networkName.Init(); - networkName.SetNetworkName(Get().GetNetworkName().GetAsData()); + networkName.SetNetworkName(Get().GetNetworkName().GetAsData()); SuccessOrExit(error = networkName.AppendTo(*message)); IgnoreError(Get().Read(dataset)); diff --git a/src/core/meshcop/meshcop.cpp b/src/core/meshcop/meshcop.cpp index 3aecc085c..cc53a3bfa 100644 --- a/src/core/meshcop/meshcop.cpp +++ b/src/core/meshcop/meshcop.cpp @@ -317,7 +317,7 @@ exit: #if OPENTHREAD_FTD Error GeneratePskc(const char * aPassPhrase, - const Mac::NetworkName & aNetworkName, + const MeshCoP::NetworkName & aNetworkName, const MeshCoP::ExtendedPanId &aExtPanId, Pskc & aPskc) { diff --git a/src/core/meshcop/meshcop.hpp b/src/core/meshcop/meshcop.hpp index c90b42a88..96b8514d8 100644 --- a/src/core/meshcop/meshcop.hpp +++ b/src/core/meshcop/meshcop.hpp @@ -421,7 +421,7 @@ private: * */ Error GeneratePskc(const char * aPassPhrase, - const Mac::NetworkName & aNetworkName, + const MeshCoP::NetworkName & aNetworkName, const MeshCoP::ExtendedPanId &aExtPanId, Pskc & aPskc); diff --git a/src/core/meshcop/meshcop_tlvs.cpp b/src/core/meshcop/meshcop_tlvs.cpp index f49729363..7c2708ad2 100644 --- a/src/core/meshcop/meshcop_tlvs.cpp +++ b/src/core/meshcop/meshcop_tlvs.cpp @@ -115,7 +115,7 @@ exit: return tlv; } -Mac::NameData NetworkNameTlv::GetNetworkName(void) const +NameData NetworkNameTlv::GetNetworkName(void) const { uint8_t len = GetLength(); @@ -124,10 +124,10 @@ Mac::NameData NetworkNameTlv::GetNetworkName(void) const len = sizeof(mNetworkName); } - return Mac::NameData(mNetworkName, len); + return NameData(mNetworkName, len); } -void NetworkNameTlv::SetNetworkName(const Mac::NameData &aNameData) +void NetworkNameTlv::SetNetworkName(const NameData &aNameData) { uint8_t len; diff --git a/src/core/meshcop/meshcop_tlvs.hpp b/src/core/meshcop/meshcop_tlvs.hpp index f701d0c2d..a7d264c73 100644 --- a/src/core/meshcop/meshcop_tlvs.hpp +++ b/src/core/meshcop/meshcop_tlvs.hpp @@ -48,6 +48,7 @@ #include "common/tlvs.hpp" #include "mac/mac_types.hpp" #include "meshcop/extended_panid.hpp" +#include "meshcop/network_name.hpp" #include "meshcop/timestamp.hpp" #include "net/ip6_address.hpp" #include "radio/radio.hpp" @@ -521,7 +522,7 @@ public: * @returns The Network Name value (as `NameData`). * */ - Mac::NameData GetNetworkName(void) const; + NameData GetNetworkName(void) const; /** * This method sets the Network Name value. @@ -529,10 +530,10 @@ public: * @param[in] aNameData A Network Name value (as `NameData`). * */ - void SetNetworkName(const Mac::NameData &aNameData); + void SetNetworkName(const NameData &aNameData); private: - char mNetworkName[Mac::NetworkName::kMaxSize]; + char mNetworkName[NetworkName::kMaxSize]; } OT_TOOL_PACKED_END; /** diff --git a/src/core/meshcop/network_name.cpp b/src/core/meshcop/network_name.cpp new file mode 100644 index 000000000..e4ae56211 --- /dev/null +++ b/src/core/meshcop/network_name.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2022, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements Network Name management. + * + */ + +#include "network_name.hpp" + +#include "common/locator_getters.hpp" +#include "common/notifier.hpp" + +namespace ot { +namespace MeshCoP { + +const char NetworkNameManager::sNetworkNameInit[] = "OpenThread"; + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +const char NetworkNameManager::sDomainNameInit[] = "DefaultDomain"; +#endif + +uint8_t NameData::CopyTo(char *aBuffer, uint8_t aMaxSize) const +{ + MutableData destData; + + destData.Init(aBuffer, aMaxSize); + destData.ClearBytes(); + IgnoreError(destData.CopyBytesFrom(*this)); + + return destData.GetLength(); +} + +NameData NetworkName::GetAsData(void) const +{ + return NameData(m8, static_cast(StringLength(m8, kMaxSize + 1))); +} + +Error NetworkName::Set(const char *aNameString) +{ + // When setting `NetworkName` from a string, we treat it as `NameData` + // with `kMaxSize + 1` chars. `NetworkName::Set(data)` will look + // for null char in the data (within its given size) to calculate + // the name's length and ensure that the name fits in `kMaxSize` + // chars. The `+ 1` ensures that a `aNameString` with length + // longer than `kMaxSize` is correctly rejected (returning error + // `kErrorInvalidArgs`). + + Error error; + NameData data(aNameString, kMaxSize + 1); + + VerifyOrExit(IsValidUtf8String(aNameString), error = kErrorInvalidArgs); + + error = Set(data); + +exit: + return error; +} + +Error NetworkName::Set(const NameData &aNameData) +{ + Error error = kErrorNone; + NameData data = aNameData; + uint8_t newLen = static_cast(StringLength(data.GetBuffer(), data.GetLength())); + + VerifyOrExit((0 < newLen) && (newLen <= kMaxSize), error = kErrorInvalidArgs); + + data.SetLength(newLen); + + // Ensure the new name does not match the current one. + if (data.MatchesBytesIn(m8) && m8[newLen] == '\0') + { + ExitNow(error = kErrorAlready); + } + + data.CopyBytesTo(m8); + m8[newLen] = '\0'; + +exit: + return error; +} + +bool NetworkName::operator==(const NetworkName &aOther) const +{ + return GetAsData() == aOther.GetAsData(); +} + +NetworkNameManager::NetworkNameManager(Instance &aInstance) + : InstanceLocator(aInstance) +{ + IgnoreError(SetNetworkName(sNetworkNameInit)); + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + IgnoreError(SetDomainName(sDomainNameInit)); +#endif +} + +Error NetworkNameManager::SetNetworkName(const char *aNameString) +{ + return SignalNetworkNameChange(mNetworkName.Set(aNameString)); +} + +Error NetworkNameManager::SetNetworkName(const NameData &aNameData) +{ + return SignalNetworkNameChange(mNetworkName.Set(aNameData)); +} + +Error NetworkNameManager::SignalNetworkNameChange(Error aError) +{ + switch (aError) + { + case kErrorNone: + Get().Signal(kEventThreadNetworkNameChanged); + break; + + case kErrorAlready: + Get().SignalIfFirst(kEventThreadNetworkNameChanged); + aError = kErrorNone; + break; + + default: + break; + } + + return aError; +} + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +Error NetworkNameManager::SetDomainName(const char *aNameString) +{ + Error error = mDomainName.Set(aNameString); + + return (error == kErrorAlready) ? kErrorNone : error; +} + +Error NetworkNameManager::SetDomainName(const NameData &aNameData) +{ + Error error = mDomainName.Set(aNameData); + + return (error == kErrorAlready) ? kErrorNone : error; +} +#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + +} // namespace MeshCoP +} // namespace ot diff --git a/src/core/meshcop/network_name.hpp b/src/core/meshcop/network_name.hpp new file mode 100644 index 000000000..1f6d84786 --- /dev/null +++ b/src/core/meshcop/network_name.hpp @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2022, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes definitions for managing the Network Name. + * + */ + +#ifndef MESHCOP_NETWORK_NAME_HPP_ +#define MESHCOP_NETWORK_NAME_HPP_ + +#include "openthread-core-config.h" + +#include + +#include "common/as_core_type.hpp" +#include "common/data.hpp" +#include "common/equatable.hpp" +#include "common/locator.hpp" +#include "common/non_copyable.hpp" +#include "common/string.hpp" + +namespace ot { +namespace MeshCoP { + +/** + * This class represents a name string as data (pointer to a char buffer along with a length). + * + * @note The char array does NOT need to be null terminated. + * + */ +class NameData : private Data +{ + friend class NetworkName; + +public: + /** + * This constructor initializes the NameData object. + * + * @param[in] aBuffer A pointer to a `char` buffer (does not need to be null terminated). + * @param[in] aLength The length (number of chars) in the buffer. + * + */ + NameData(const char *aBuffer, uint8_t aLength) { Init(aBuffer, aLength); } + + /** + * This method returns the pointer to char buffer (not necessarily null terminated). + * + * @returns The pointer to the char buffer. + * + */ + const char *GetBuffer(void) const { return reinterpret_cast(GetBytes()); } + + /** + * This method returns the length (number of chars in buffer). + * + * @returns The name length. + * + */ + uint8_t GetLength(void) const { return Data::GetLength(); } + + /** + * This method copies the name data into a given char buffer with a given size. + * + * The given buffer is cleared (`memset` to zero) before copying the name into it. The copied string + * in @p aBuffer is NOT necessarily null terminated. + * + * @param[out] aBuffer A pointer to a buffer where to copy the name into. + * @param[in] aMaxSize Size of @p aBuffer (maximum number of chars to write into @p aBuffer). + * + * @returns The actual number of chars copied into @p aBuffer. + * + */ + uint8_t CopyTo(char *aBuffer, uint8_t aMaxSize) const; +}; + +/** + * This structure represents an Network Name. + * + */ +class NetworkName : public otNetworkName, public Unequatable +{ +public: + /** + * This constant specified the maximum number of chars in Network Name (excludes null char). + * + */ + static constexpr uint8_t kMaxSize = OT_NETWORK_NAME_MAX_SIZE; + + /** + * This constructor initializes the Network Name as an empty string. + * + */ + NetworkName(void) { m8[0] = '\0'; } + + /** + * This method gets the Network Name as a null terminated C string. + * + * @returns The Network Name as a null terminated C string array. + * + */ + const char *GetAsCString(void) const { return m8; } + + /** + * This method gets the Network Name as NameData. + * + * @returns The Network Name as NameData. + * + */ + NameData GetAsData(void) const; + + /** + * This method sets the Network Name from a given null terminated C string. + * + * This method also validates that the given @p aNameString follows UTF-8 encoding and can fit in `kMaxSize` + * chars. + * + * @param[in] aNameString A name C string. + * + * @retval kErrorNone Successfully set the Network Name. + * @retval kErrorAlready The name is already set to the same string. + * @retval kErrorInvalidArgs Given name is invalid (too long or does not follow UTF-8 encoding). + * + */ + Error Set(const char *aNameString); + + /** + * This method sets the Network Name. + * + * @param[in] aNameData A reference to name data. + * + * @retval kErrorNone Successfully set the Network Name. + * @retval kErrorAlready The name is already set to the same string. + * @retval kErrorInvalidArgs Given name is too long. + * + */ + Error Set(const NameData &aNameData); + + /** + * This method overloads operator `==` to evaluate whether or not two given `NetworkName` objects are equal. + * + * @param[in] aOther The other `NetworkName` to compare with. + * + * @retval TRUE If the two are equal. + * @retval FALSE If the two are not equal. + * + */ + bool operator==(const NetworkName &aOther) const; +}; + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +/** + * This type represents a Thread Domain Name. + * + */ +typedef NetworkName DomainName; +#endif + +/** + * This class manages the Network Name value. + * + */ +class NetworkNameManager : public InstanceLocator, private NonCopyable +{ +public: + /** + * Constructor. + * + * @param[in] aInstance A reference to the OpenThread instance. + * + */ + explicit NetworkNameManager(Instance &aInstance); + + /** + * This method returns the Network Name. + * + * @returns The Network Name. + * + */ + const NetworkName &GetNetworkName(void) const { return mNetworkName; } + + /** + * This method sets the Network Name. + * + * @param[in] aNameString A pointer to a string character array. Must be null terminated. + * + * @retval kErrorNone Successfully set the Network Name. + * @retval kErrorInvalidArgs Given name is too long. + * + */ + Error SetNetworkName(const char *aNameString); + + /** + * This method sets the Network Name. + * + * @param[in] aNameData A name data (pointer to char buffer and length). + * + * @retval kErrorNone Successfully set the Network Name. + * @retval kErrorInvalidArgs Given name is too long. + * + */ + Error SetNetworkName(const NameData &aNameData); + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + /** + * This method returns the Thread Domain Name. + * + * @returns The Thread Domain Name. + * + */ + const DomainName &GetDomainName(void) const { return mDomainName; } + + /** + * This method sets the Thread Domain Name. + * + * @param[in] aNameString A pointer to a string character array. Must be null terminated. + * + * @retval kErrorNone Successfully set the Thread Domain Name. + * @retval kErrorInvalidArgs Given name is too long. + * + */ + Error SetDomainName(const char *aNameString); + + /** + * This method sets the Thread Domain Name. + * + * @param[in] aNameData A name data (pointer to char buffer and length). + * + * @retval kErrorNone Successfully set the Thread Domain Name. + * @retval kErrorInvalidArgs Given name is too long. + * + */ + Error SetDomainName(const NameData &aNameData); +#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + +private: + Error SignalNetworkNameChange(Error aError); + + static const char sNetworkNameInit[]; + static const char sDomainNameInit[]; + + NetworkName mNetworkName; + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + DomainName mDomainName; +#endif +}; + +} // namespace MeshCoP + +DefineCoreType(otNetworkName, MeshCoP::NetworkName); + +} // namespace ot + +#endif // MESHCOP_EXTENDED_PANID_HPP_ diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index a6f0d3046..5bab2f6c4 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -3023,7 +3023,7 @@ Error MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, const M // Network Name TLV networkName.Init(); - networkName.SetNetworkName(Get().GetNetworkName().GetAsData()); + networkName.SetNetworkName(Get().GetNetworkName().GetAsData()); SuccessOrExit(error = networkName.AppendTo(*message)); #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp index 8ecbd4a0d..7cc880c73 100644 --- a/src/core/thread/thread_netif.cpp +++ b/src/core/thread/thread_netif.cpp @@ -83,6 +83,7 @@ ThreadNetif::ThreadNetif(Instance &aInstance) , mActiveDataset(aInstance) , mPendingDataset(aInstance) , mExtendedPanIdManager(aInstance) + , mNetworkNameManager(aInstance) , mIp6Filter(aInstance) , mKeyManager(aInstance) , mLowpan(aInstance) diff --git a/src/core/thread/thread_netif.hpp b/src/core/thread/thread_netif.hpp index 8f28b7bee..7d8662f3d 100644 --- a/src/core/thread/thread_netif.hpp +++ b/src/core/thread/thread_netif.hpp @@ -49,6 +49,7 @@ #include "meshcop/joiner.hpp" #include "meshcop/joiner_router.hpp" #include "meshcop/meshcop_leader.hpp" +#include "meshcop/network_name.hpp" #include "net/dhcp6.hpp" #include "net/dhcp6_client.hpp" #include "net/dhcp6_server.hpp" @@ -201,6 +202,7 @@ private: MeshCoP::ActiveDataset mActiveDataset; MeshCoP::PendingDataset mPendingDataset; MeshCoP::ExtendedPanIdManager mExtendedPanIdManager; + MeshCoP::NetworkNameManager mNetworkNameManager; Ip6::Filter mIp6Filter; KeyManager mKeyManager; Lowpan::Lowpan mLowpan; diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 5c41d060e..a7d58ed79 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -645,6 +645,27 @@ add_executable(ot-test-ndproxy-table test_ndproxy_table.cpp ) +add_executable(ot-test-network-name + test_network_name.cpp +) + +target_include_directories(ot-test-network-name + PRIVATE + ${COMMON_INCLUDES} +) + +target_compile_options(ot-test-network-name + PRIVATE + ${COMMON_COMPILE_OPTIONS} +) + +target_link_libraries(ot-test-network-name + PRIVATE + ${COMMON_LIBS} +) + +add_test(NAME ot-test-network-name COMMAND ot-test-network-name) + target_include_directories(ot-test-ndproxy-table PRIVATE ${COMMON_INCLUDES} diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index 21e671ca1..df54384bd 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -142,6 +142,7 @@ check_PROGRAMS += \ ot-test-ndproxy-table \ ot-test-netif \ ot-test-network-data \ + ot-test-network-name \ ot-test-pool \ ot-test-priority-queue \ ot-test-pskc \ @@ -301,6 +302,10 @@ ot_test_multicast_listeners_table_LDADD = $(COMMON_LDADD) ot_test_multicast_listeners_table_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS) ot_test_multicast_listeners_table_SOURCES = $(COMMON_SOURCES) test_multicast_listeners_table.cpp +ot_test_network_name_LDADD = $(COMMON_LDADD) +ot_test_network_name_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS) +ot_test_network_name_SOURCES = $(COMMON_SOURCES) test_network_name.cpp + ot_test_spinel_buffer_LDADD = $(COMMON_LDADD) ot_test_spinel_buffer_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS) ot_test_spinel_buffer_SOURCES = $(COMMON_SOURCES) test_spinel_buffer.cpp diff --git a/tests/unit/test_mac_frame.cpp b/tests/unit/test_mac_frame.cpp index b5d5796d6..5aac167cc 100644 --- a/tests/unit/test_mac_frame.cpp +++ b/tests/unit/test_mac_frame.cpp @@ -154,85 +154,6 @@ void TestMacAddress(void) testFreeInstance(instance); } -void CompareNetworkName(const Mac::NetworkName &aNetworkName, const char *aNameString) -{ - uint8_t len = static_cast(strlen(aNameString)); - - VerifyOrQuit(strcmp(aNetworkName.GetAsCString(), aNameString) == 0); - - VerifyOrQuit(aNetworkName.GetAsData().GetLength() == len); - VerifyOrQuit(memcmp(aNetworkName.GetAsData().GetBuffer(), aNameString, len) == 0); -} - -void TestMacNetworkName(void) -{ - const char kEmptyName[] = ""; - const char kName1[] = "network"; - const char kName2[] = "network-name"; - const char kLongName[] = "0123456789abcdef"; - const char kTooLongName[] = "0123456789abcdef0"; - - char buffer[sizeof(kTooLongName) + 2]; - uint8_t len; - Mac::NetworkName networkName; - Mac::NetworkName networkName2; - - CompareNetworkName(networkName, kEmptyName); - - SuccessOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1)))); - CompareNetworkName(networkName, kName1); - - VerifyOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1))) == kErrorAlready, "failed to detect duplicate"); - CompareNetworkName(networkName, kName1); - - VerifyOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1) - 1)) == kErrorAlready, - "failed to detect duplicate"); - - SuccessOrQuit(networkName.Set(Mac::NameData(kName2, sizeof(kName2)))); - CompareNetworkName(networkName, kName2); - - VerifyOrQuit(networkName.Set(Mac::NameData(kEmptyName, 0)) == kErrorInvalidArgs); - - SuccessOrQuit(networkName.Set(Mac::NameData(kLongName, sizeof(kLongName)))); - CompareNetworkName(networkName, kLongName); - - VerifyOrQuit(networkName.Set(Mac::NameData(kLongName, sizeof(kLongName) - 1)) == kErrorAlready, - "failed to detect duplicate"); - - VerifyOrQuit(networkName.Set(kEmptyName) == kErrorInvalidArgs); - - SuccessOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1)))); - - VerifyOrQuit(networkName.Set(Mac::NameData(kTooLongName, sizeof(kTooLongName))) == kErrorInvalidArgs, - "accepted an invalid (too long) name"); - - CompareNetworkName(networkName, kName1); - - memset(buffer, 'a', sizeof(buffer)); - len = networkName.GetAsData().CopyTo(buffer, 1); - VerifyOrQuit(len == 1, "NameData::CopyTo() failed"); - VerifyOrQuit(buffer[0] == kName1[0], "NameData::CopyTo() failed"); - VerifyOrQuit(buffer[1] == 'a', "NameData::CopyTo() failed"); - - memset(buffer, 'a', sizeof(buffer)); - len = networkName.GetAsData().CopyTo(buffer, sizeof(kName1) - 1); - VerifyOrQuit(len == sizeof(kName1) - 1, "NameData::CopyTo() failed"); - VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NameData::CopyTo() failed"); - VerifyOrQuit(buffer[sizeof(kName1)] == 'a', "NameData::CopyTo() failed"); - - memset(buffer, 'a', sizeof(buffer)); - len = networkName.GetAsData().CopyTo(buffer, sizeof(buffer)); - VerifyOrQuit(len == sizeof(kName1) - 1, "NameData::CopyTo() failed"); - VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NameData::CopyTo() failed"); - VerifyOrQuit(buffer[sizeof(kName1)] == 0, "NameData::CopyTo() failed"); - - SuccessOrQuit(networkName2.Set(Mac::NameData(kName1, sizeof(kName1)))); - VerifyOrQuit(networkName == networkName2); - - SuccessOrQuit(networkName2.Set(kName2)); - VerifyOrQuit(networkName != networkName2); -} - void TestMacHeader(void) { static const struct @@ -650,7 +571,6 @@ void TestMacFrameAckGeneration(void) int main(void) { ot::TestMacAddress(); - ot::TestMacNetworkName(); ot::TestMacHeader(); ot::TestMacChannelMask(); ot::TestMacFrameApi(); diff --git a/tests/unit/test_network_name.cpp b/tests/unit/test_network_name.cpp new file mode 100644 index 000000000..c1f448fe4 --- /dev/null +++ b/tests/unit/test_network_name.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2022, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "common/code_utils.hpp" +#include "common/debug.hpp" +#include "meshcop/network_name.hpp" + +#include "test_util.h" + +namespace ot { + +void CompareNetworkName(const MeshCoP::NetworkName &aNetworkName, const char *aNameString) +{ + uint8_t len = static_cast(strlen(aNameString)); + + VerifyOrQuit(strcmp(aNetworkName.GetAsCString(), aNameString) == 0); + + VerifyOrQuit(aNetworkName.GetAsData().GetLength() == len); + VerifyOrQuit(memcmp(aNetworkName.GetAsData().GetBuffer(), aNameString, len) == 0); +} + +void TestNetworkName(void) +{ + const char kEmptyName[] = ""; + const char kName1[] = "network"; + const char kName2[] = "network-name"; + const char kLongName[] = "0123456789abcdef"; + const char kTooLongName[] = "0123456789abcdef0"; + + char buffer[sizeof(kTooLongName) + 2]; + uint8_t len; + MeshCoP::NetworkName networkName; + MeshCoP::NetworkName networkName2; + + CompareNetworkName(networkName, kEmptyName); + + SuccessOrQuit(networkName.Set(MeshCoP::NameData(kName1, sizeof(kName1)))); + CompareNetworkName(networkName, kName1); + + VerifyOrQuit(networkName.Set(MeshCoP::NameData(kName1, sizeof(kName1))) == kErrorAlready, + "failed to detect duplicate"); + CompareNetworkName(networkName, kName1); + + VerifyOrQuit(networkName.Set(MeshCoP::NameData(kName1, sizeof(kName1) - 1)) == kErrorAlready, + "failed to detect duplicate"); + + SuccessOrQuit(networkName.Set(MeshCoP::NameData(kName2, sizeof(kName2)))); + CompareNetworkName(networkName, kName2); + + VerifyOrQuit(networkName.Set(MeshCoP::NameData(kEmptyName, 0)) == kErrorInvalidArgs); + + SuccessOrQuit(networkName.Set(MeshCoP::NameData(kLongName, sizeof(kLongName)))); + CompareNetworkName(networkName, kLongName); + + VerifyOrQuit(networkName.Set(MeshCoP::NameData(kLongName, sizeof(kLongName) - 1)) == kErrorAlready, + "failed to detect duplicate"); + + VerifyOrQuit(networkName.Set(kEmptyName) == kErrorInvalidArgs); + + SuccessOrQuit(networkName.Set(MeshCoP::NameData(kName1, sizeof(kName1)))); + + VerifyOrQuit(networkName.Set(MeshCoP::NameData(kTooLongName, sizeof(kTooLongName))) == kErrorInvalidArgs, + "accepted an invalid (too long) name"); + + CompareNetworkName(networkName, kName1); + + memset(buffer, 'a', sizeof(buffer)); + len = networkName.GetAsData().CopyTo(buffer, 1); + VerifyOrQuit(len == 1, "NameData::CopyTo() failed"); + VerifyOrQuit(buffer[0] == kName1[0], "NameData::CopyTo() failed"); + VerifyOrQuit(buffer[1] == 'a', "NameData::CopyTo() failed"); + + memset(buffer, 'a', sizeof(buffer)); + len = networkName.GetAsData().CopyTo(buffer, sizeof(kName1) - 1); + VerifyOrQuit(len == sizeof(kName1) - 1, "NameData::CopyTo() failed"); + VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NameData::CopyTo() failed"); + VerifyOrQuit(buffer[sizeof(kName1)] == 'a', "NameData::CopyTo() failed"); + + memset(buffer, 'a', sizeof(buffer)); + len = networkName.GetAsData().CopyTo(buffer, sizeof(buffer)); + VerifyOrQuit(len == sizeof(kName1) - 1, "NameData::CopyTo() failed"); + VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NameData::CopyTo() failed"); + VerifyOrQuit(buffer[sizeof(kName1)] == 0, "NameData::CopyTo() failed"); + + SuccessOrQuit(networkName2.Set(MeshCoP::NameData(kName1, sizeof(kName1)))); + VerifyOrQuit(networkName == networkName2); + + SuccessOrQuit(networkName2.Set(kName2)); + VerifyOrQuit(networkName != networkName2); +} + +} // namespace ot + +int main(void) +{ + ot::TestNetworkName(); + printf("All tests passed\n"); + return 0; +} diff --git a/tests/unit/test_pskc.cpp b/tests/unit/test_pskc.cpp index f7a536479..3eedad98f 100644 --- a/tests/unit/test_pskc.cpp +++ b/tests/unit/test_pskc.cpp @@ -43,7 +43,8 @@ void TestMinimumPassphrase(void) const otExtendedPanId xpanid = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}}; const char passphrase[] = "123456"; otInstance * instance = testInitInstance(); - SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast("OpenThread"), + SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, + *reinterpret_cast("OpenThread"), static_cast(xpanid), pskc)); VerifyOrQuit(memcmp(pskc.m8, expectedPskc, OT_PSKC_MAX_SIZE) == 0); testFreeInstance(instance); @@ -73,7 +74,8 @@ void TestMaximumPassphrase(void) "123456781234567"; otInstance *instance = testInitInstance(); - SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast("OpenThread"), + SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, + *reinterpret_cast("OpenThread"), static_cast(xpanid), pskc)); VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc.m8)) == 0); testFreeInstance(instance); @@ -88,7 +90,8 @@ void TestExampleInSpec(void) const char passphrase[] = "12SECRETPASSWORD34"; otInstance *instance = testInitInstance(); - SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast("Test Network"), + SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, + *reinterpret_cast("Test Network"), static_cast(xpanid), pskc)); VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc.m8)) == 0); testFreeInstance(instance);