diff --git a/src/core/api/thread_api.cpp b/src/core/api/thread_api.cpp index b2f830b23..96a8832ea 100644 --- a/src/core/api/thread_api.cpp +++ b/src/core/api/thread_api.cpp @@ -185,7 +185,7 @@ const char *otThreadGetNetworkName(otInstance *aInstance) { Instance &instance = *static_cast(aInstance); - return instance.Get().GetNetworkName(); + return instance.Get().GetNetworkName().GetAsCString(); } otError otThreadSetNetworkName(otInstance *aInstance, const char *aNetworkName) diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index d89a85d84..feafc03ba 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -97,6 +97,7 @@ Mac::Mac(Instance &aInstance) , mRadioChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL) , mRadioChannelAcquisitionId(0) , mSupportedChannelMask(Get().GetSupportedChannelMask()) + , mNetworkName() , mScanChannel(Radio::kChannelMin) , mScanDuration(0) , mScanChannelMask() @@ -117,7 +118,6 @@ Mac::Mac(Instance &aInstance) mCcaSuccessRateTracker.Reset(); memset(&mCounters, 0, sizeof(otMacCounters)); - memset(&mNetworkName, 0, sizeof(otNetworkName)); memset(&mExtendedPanId, 0, sizeof(ExtendedPanId)); mSubMac.Enable(); @@ -238,7 +238,7 @@ otError Mac::ConvertBeaconToActiveScanResult(RxFrame *aBeaconFrame, otActiveScan aResult.mVersion = beaconPayload->GetProtocolVersion(); aResult.mIsJoinable = beaconPayload->IsJoiningPermitted(); aResult.mIsNative = beaconPayload->IsNative(); - memcpy(&aResult.mNetworkName, beaconPayload->GetNetworkName(), BeaconPayload::kNetworkNameSize); + static_cast(aResult.mNetworkName).Set(beaconPayload->GetNetworkName()); aResult.mExtendedPanId = beaconPayload->GetExtendedPanId(); } @@ -446,17 +446,33 @@ exit: return; } -otError Mac::SetNetworkName(const char *aBuffer, uint8_t aLength) +otError Mac::SetNetworkName(const char *aNameString) { - otError error = OT_ERROR_NONE; - uint8_t newLen = static_cast(strnlen(aBuffer, aLength)); + // When setting Network Name from a string, we treat it as `Data` + // 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 + // `OT_ERROR_INVALID_ARGS`). - VerifyOrExit(newLen <= OT_NETWORK_NAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS); - VerifyOrExit(newLen != strlen(mNetworkName.m8) || memcmp(mNetworkName.m8, aBuffer, newLen) != 0, - Get().SignalIfFirst(OT_CHANGED_THREAD_NETWORK_NAME)); + NetworkName::Data data(aNameString, NetworkName::kMaxSize + 1); - memcpy(mNetworkName.m8, aBuffer, newLen); - mNetworkName.m8[newLen] = 0; + return SetNetworkName(data); +} + +otError Mac::SetNetworkName(const NetworkName::Data &aName) +{ + otError error = mNetworkName.Set(aName); + + if (error == OT_ERROR_ALREADY) + { + Get().SignalIfFirst(OT_CHANGED_THREAD_NETWORK_NAME); + error = OT_ERROR_NONE; + ExitNow(); + } + + SuccessOrExit(error); Get().Signal(OT_CHANGED_THREAD_NETWORK_NAME); exit: @@ -844,7 +860,7 @@ void Mac::PrepareBeacon(TxFrame &aFrame) beaconPayload->ClearJoiningPermitted(); } - beaconPayload->SetNetworkName(mNetworkName.m8); + beaconPayload->SetNetworkName(mNetworkName.GetAsData()); beaconPayload->SetExtendedPanId(mExtendedPanId); beaconLength += sizeof(*beaconPayload); diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index ed8d77bc5..b09524c7c 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -366,36 +366,32 @@ public: /** * This method returns the IEEE 802.15.4 Network Name. * - * @returns A pointer to the IEEE 802.15.4 Network Name. + * @returns The IEEE 802.15.4 Network Name. * */ - const char *GetNetworkName(void) const { return mNetworkName.m8; } + const NetworkName &GetNetworkName(void) const { return mNetworkName; } /** * This method sets the IEEE 802.15.4 Network Name. * - * @param[in] aNetworkName A pointer to the string. Must be null terminated. + * @param[in] aNameString A pointer to a string character array. Must be null terminated. * * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Network Name. * @retval OT_ERROR_INVALID_ARGS Given name is too long. * */ - otError SetNetworkName(const char *aNetworkName) - { - return SetNetworkName(aNetworkName, OT_NETWORK_NAME_MAX_SIZE + 1); - } + otError SetNetworkName(const char *aNameString); /** * This method sets the IEEE 802.15.4 Network Name. * - * @param[in] aBuffer A pointer to the char buffer containing the name. Does not need to be null terminated. - * @param[in] aLength Number of chars in the buffer. + * @param[in] aNameData A name data (pointer to char buffer and length). * * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Network Name. * @retval OT_ERROR_INVALID_ARGS Given name is too long. * */ - otError SetNetworkName(const char *aBuffer, uint8_t aLength); + otError SetNetworkName(const NetworkName::Data &aNameData); /** * This method returns the IEEE 802.15.4 PAN ID. @@ -713,7 +709,7 @@ private: uint16_t mRadioChannelAcquisitionId; ChannelMask mSupportedChannelMask; ExtendedPanId mExtendedPanId; - otNetworkName mNetworkName; + NetworkName mNetworkName; uint8_t mScanChannel; uint16_t mScanDuration; ChannelMask mScanChannelMask; diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp index 7d1ae8c33..ce2aa72d0 100644 --- a/src/core/mac/mac_frame.cpp +++ b/src/core/mac/mac_frame.cpp @@ -95,6 +95,46 @@ ExtendedPanId::InfoString ExtendedPanId::ToString(void) const return InfoString("%02x%02x%02x%02x%02x%02x%02x%02x", m8[0], m8[1], m8[2], m8[3], m8[4], m8[5], m8[6], m8[7]); } +uint8_t NetworkName::Data::CopyTo(char *aBuffer, uint8_t aMaxSize) const +{ + uint8_t len = GetLength(); + + memset(aBuffer, 0, aMaxSize); + + if (len > aMaxSize) + { + len = aMaxSize; + } + + memcpy(aBuffer, GetBuffer(), len); + + return len; +} + +NetworkName::Data NetworkName::GetAsData(void) const +{ + uint8_t len = static_cast(strnlen(m8, kMaxSize + 1)); + + return Data(m8, len); +} + +otError NetworkName::Set(const Data &aNameData) +{ + otError error = OT_ERROR_NONE; + uint8_t newLen = static_cast(strnlen(aNameData.GetBuffer(), aNameData.GetLength())); + + VerifyOrExit(newLen <= kMaxSize, error = OT_ERROR_INVALID_ARGS); + + // Ensure the new name does not match the current one. + VerifyOrExit(memcmp(m8, aNameData.GetBuffer(), newLen) || (m8[newLen] != '\0'), error = OT_ERROR_ALREADY); + + memcpy(m8, aNameData.GetBuffer(), newLen); + m8[newLen] = '\0'; + +exit: + return error; +} + void Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl) { uint8_t *bytes = GetPsdu(); @@ -1129,11 +1169,11 @@ Frame::InfoString Frame::ToInfoString(void) const BeaconPayload::InfoString BeaconPayload::ToInfoString(void) const { - otNetworkName networkname; + NetworkName name; - strlcpy(networkname.m8, GetNetworkName(), sizeof(networkname.m8)); + name.Set(GetNetworkName()); - return InfoString("name:%s, xpanid:%s, id:%d, ver:%d, joinable:%s, native:%s", networkname.m8, + return InfoString("name:%s, xpanid:%s, id:%d, ver:%d, joinable:%s, native:%s", name.GetAsCString(), mExtendedPanId.ToString().AsCString(), GetProtocolId(), GetProtocolVersion(), IsJoiningPermitted() ? "yes" : "no", IsNative() ? "yes" : "no"); } diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp index 9daf15314..a22b2b08f 100644 --- a/src/core/mac/mac_frame.hpp +++ b/src/core/mac/mac_frame.hpp @@ -475,6 +475,110 @@ public: } OT_TOOL_PACKED_END; +/** + * This structure represents an IEEE802.15.4 Network Name. + * + */ +class NetworkName : public otNetworkName +{ +public: + enum + { + kMaxSize = OT_NETWORK_NAME_MAX_SIZE, // Maximum number of chars in Network Name (excludes null char). + }; + + /** + * This class represents an IEEE802.15.4 Network Name as Data (pointer to a char buffer along with a length). + * + * @note The char array does NOT need to be null terminated. + * + */ + class Data + { + public: + /** + * This constructor initializes the Data 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. + * + */ + Data(const char *aBuffer, uint8_t aLength) + : mBuffer(aBuffer) + , mLength(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 mBuffer; } + + /** + * This method returns the length (number of chars in buffer). + * + * @returns The name length. + * + */ + uint8_t GetLength(void) const { return mLength; } + + /** + * 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 Network 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 Network 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; + + private: + const char *mBuffer; + uint8_t mLength; + }; + + /** + * 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 Data. + * + * @returns The Network Name as Data. + * + */ + Data GetAsData(void) const; + + /** + * This method sets the IEEE 802.15.4 Network Name. + * + * @param[in] aNameData A reference to name data. + * + * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Network Name. + * @retval OT_ERROR_ALREADY The name is already set to the same string. + * @retval OT_ERROR_INVALID_ARGS Given name is too long. + * + */ + otError Set(const Data &aNameData); +}; + /** * This class implements IEEE 802.15.4 IE (Information Element) generation and parsing. * @@ -1591,9 +1695,8 @@ class BeaconPayload public: enum { - kProtocolId = 3, ///< Thread Protocol ID. - kNetworkNameSize = 16, ///< Size of Thread Network Name (bytes). - kInfoStringSize = 92, ///< Max chars for the info string (@sa ToInfoString()). + kProtocolId = 3, ///< Thread Protocol ID. + kInfoStringSize = 92, ///< Max chars for the info string (@sa ToInfoString()). }; enum @@ -1697,25 +1800,20 @@ public: } /** - * This method returns a pointer to the Network Name field. + * This method gets the Network Name field. * - * @returns A pointer to the network name field. + * @returns The Network Name field as `NetworkName::Data`. * */ - const char *GetNetworkName(void) const { return mNetworkName; } + NetworkName::Data GetNetworkName(void) const { return NetworkName::Data(mNetworkName, sizeof(mNetworkName)); } /** * This method sets the Network Name field. * - * @param[in] aNetworkName A pointer to the Network Name. + * @param[in] aNameData The Network Name (as a `NetworkName::Data`). * */ - void SetNetworkName(const char *aNetworkName) - { - size_t length = strnlen(aNetworkName, sizeof(mNetworkName)); - memset(mNetworkName, 0, sizeof(mNetworkName)); - memcpy(mNetworkName, aNetworkName, length); - } + void SetNetworkName(const NetworkName::Data &aNameData) { aNameData.CopyTo(mNetworkName, sizeof(mNetworkName)); } /** * This method returns the Extended PAN ID field. @@ -1744,7 +1842,7 @@ public: private: uint8_t mProtocolId; uint8_t mFlags; - char mNetworkName[kNetworkNameSize]; + char mNetworkName[NetworkName::kMaxSize]; ExtendedPanId mExtendedPanId; } OT_TOOL_PACKED_END; diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp index 4176497b9..80ffb9b12 100644 --- a/src/core/meshcop/dataset.cpp +++ b/src/core/meshcop/dataset.cpp @@ -191,8 +191,7 @@ void Dataset::Get(otOperationalDataset &aDataset) const case Tlv::kNetworkName: { const NetworkNameTlv *tlv = static_cast(cur); - memcpy(aDataset.mNetworkName.m8, tlv->GetNetworkName(), tlv->GetLength()); - aDataset.mNetworkName.m8[tlv->GetLength()] = '\0'; + static_cast(aDataset.mNetworkName).Set(tlv->GetNetworkName()); aDataset.mComponents.mIsNetworkNamePresent = true; break; } @@ -328,7 +327,7 @@ otError Dataset::Set(const otOperationalDataset &aDataset) { MeshCoP::NetworkNameTlv tlv; tlv.Init(); - tlv.SetNetworkName(aDataset.mNetworkName.m8); + tlv.SetNetworkName(static_cast(aDataset.mNetworkName).GetAsData()); Set(tlv); } @@ -556,7 +555,7 @@ otError Dataset::ApplyConfiguration(Instance &aInstance, bool *aIsMasterKeyUpdat case Tlv::kNetworkName: { const NetworkNameTlv *name = static_cast(cur); - mac.SetNetworkName(name->GetNetworkName(), name->GetLength()); + mac.SetNetworkName(name->GetNetworkName()); break; } diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp index 2481f84ec..2fd4aa7e3 100644 --- a/src/core/meshcop/dataset_manager.cpp +++ b/src/core/meshcop/dataset_manager.cpp @@ -478,7 +478,7 @@ otError DatasetManager::SendSetRequest(const otOperationalDataset &aDataset, con { NetworkNameTlv networkname; networkname.Init(); - networkname.SetNetworkName(aDataset.mNetworkName.m8); + networkname.SetNetworkName(static_cast(aDataset.mNetworkName).GetAsData()); SuccessOrExit(error = message->AppendTlv(networkname)); } diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp index 72062a1fb..786bd1f7d 100644 --- a/src/core/meshcop/dataset_manager_ftd.cpp +++ b/src/core/meshcop/dataset_manager_ftd.cpp @@ -436,7 +436,7 @@ otError ActiveDataset::GenerateLocal(void) { NetworkNameTlv tlv; tlv.Init(); - tlv.SetNetworkName(Get().GetNetworkName()); + tlv.SetNetworkName(Get().GetNetworkName().GetAsData()); dataset.Set(tlv); } diff --git a/src/core/meshcop/joiner.cpp b/src/core/meshcop/joiner.cpp index 9a25fcc6c..965d87e50 100644 --- a/src/core/meshcop/joiner.cpp +++ b/src/core/meshcop/joiner.cpp @@ -557,7 +557,7 @@ void Joiner::HandleJoinerEntrust(Coap::Message &aMessage, const Ip6::MessageInfo Get().SetMeshLocalPrefix(meshLocalPrefix.GetMeshLocalPrefix()); Get().SetExtendedPanId(extendedPanId.GetExtendedPanId()); - Get().SetNetworkName(networkName.GetNetworkName(), networkName.GetNetworkNameLength()); + Get().SetNetworkName(networkName.GetNetworkName()); otLogInfoMeshCoP("Joiner successful!"); diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp index e2467d622..09e019f00 100644 --- a/src/core/meshcop/joiner_router.cpp +++ b/src/core/meshcop/joiner_router.cpp @@ -297,7 +297,7 @@ otError JoinerRouter::DelaySendingJoinerEntrust(const Ip6::MessageInfo &aMessage SuccessOrExit(error = message->AppendTlv(extendedPanId)); networkName.Init(); - networkName.SetNetworkName(Get().GetNetworkName()); + networkName.SetNetworkName(Get().GetNetworkName().GetAsData()); SuccessOrExit(error = message->AppendTlv(networkName)); Get().Read(dataset); diff --git a/src/core/meshcop/meshcop_tlvs.cpp b/src/core/meshcop/meshcop_tlvs.cpp index 33858f473..51d3e730d 100644 --- a/src/core/meshcop/meshcop_tlvs.cpp +++ b/src/core/meshcop/meshcop_tlvs.cpp @@ -83,6 +83,26 @@ bool Tlv::IsValid(const Tlv &aTlv) return rval; } +Mac::NetworkName::Data NetworkNameTlv::GetNetworkName(void) const +{ + uint8_t len = GetLength(); + + if (len > sizeof(mNetworkName)) + { + len = sizeof(mNetworkName); + } + + return Mac::NetworkName::Data(mNetworkName, len); +} + +void NetworkNameTlv::SetNetworkName(const Mac::NetworkName::Data &aNameData) +{ + uint8_t len; + + len = aNameData.CopyTo(mNetworkName, sizeof(mNetworkName)); + SetLength(len); +} + bool SteeringDataTlv::IsCleared(void) const { bool rval = true; diff --git a/src/core/meshcop/meshcop_tlvs.hpp b/src/core/meshcop/meshcop_tlvs.hpp index 132bb01cb..900a9c885 100644 --- a/src/core/meshcop/meshcop_tlvs.hpp +++ b/src/core/meshcop/meshcop_tlvs.hpp @@ -405,39 +405,23 @@ public: bool IsValid(void) const { return true; } /** - * This method returns the Network Name length. + * This method gets the Network Name value. * - * @returns The Network Name length. + * @returns The Network Name value (as `NetworkName::Data`). * */ - uint8_t GetNetworkNameLength(void) const - { - return GetLength() <= sizeof(mNetworkName) ? GetLength() : sizeof(mNetworkName); - } - - /** - * This method returns the Network Name value. - * - * @returns The Network Name value. - * - */ - const char *GetNetworkName(void) const { return mNetworkName; } + Mac::NetworkName::Data GetNetworkName(void) const; /** * This method sets the Network Name value. * - * @param[in] aNetworkName A pointer to the Network Name value. + * @param[in] aNameData A Network Name value (as `NetworkName::Data`). * */ - void SetNetworkName(const char *aNetworkName) - { - size_t length = strnlen(aNetworkName, sizeof(mNetworkName)); - memcpy(mNetworkName, aNetworkName, length); - SetLength(static_cast(length)); - } + void SetNetworkName(const Mac::NetworkName::Data &aNameData); private: - char mNetworkName[OT_NETWORK_NAME_MAX_SIZE]; + char mNetworkName[Mac::NetworkName::kMaxSize]; } OT_TOOL_PACKED_END; /** diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 88bb21510..4ba915a4e 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -3825,8 +3825,7 @@ otError Mle::HandleDiscoveryResponse(const Message &aMessage, const Ip6::Message case MeshCoP::Tlv::kNetworkName: aMessage.Read(offset, sizeof(networkName), &networkName); - memcpy(&result.mNetworkName, networkName.GetNetworkName(), networkName.GetNetworkNameLength()); - result.mNetworkName.m8[networkName.GetNetworkNameLength()] = '\0'; + static_cast(result.mNetworkName).Set(networkName.GetNetworkName()); break; case MeshCoP::Tlv::kSteeringData: diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index c7646d79f..dafe03192 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -2761,7 +2761,7 @@ otError MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, uint1 // Network Name TLV networkName.Init(); - networkName.SetNetworkName(Get().GetNetworkName()); + networkName.SetNetworkName(Get().GetNetworkName().GetAsData()); SuccessOrExit(error = message->AppendTlv(networkName)); #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE diff --git a/tests/unit/test_mac_frame.cpp b/tests/unit/test_mac_frame.cpp index 88f9373d8..4a738840f 100644 --- a/tests/unit/test_mac_frame.cpp +++ b/tests/unit/test_mac_frame.cpp @@ -155,6 +155,82 @@ 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, "NetworkName does not match expected value\n"); + + VerifyOrQuit(aNetworkName.GetAsData().GetLength() == len, "NetworkName:GetAsData().GetLength() is incorrect\n"); + VerifyOrQuit(memcmp(aNetworkName.GetAsData().GetBuffer(), aNameString, len) == 0, + "NetworkName:GetAsData().GetBuffer() is incorrect\n"); +} + +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; + + CompareNetworkName(networkName, kEmptyName); + + SuccessOrQuit(networkName.Set(Mac::NetworkName::Data(kName1, sizeof(kName1))), "NetworkName::Set() failed\n"); + CompareNetworkName(networkName, kName1); + + VerifyOrQuit(networkName.Set(Mac::NetworkName::Data(kName1, sizeof(kName1))) == OT_ERROR_ALREADY, + "NetworkName::Set() accepted same name without returning OT_ERROR_ALREADY"); + CompareNetworkName(networkName, kName1); + + VerifyOrQuit(networkName.Set(Mac::NetworkName::Data(kName1, sizeof(kName1) - 1)) == OT_ERROR_ALREADY, + "NetworkName::Set() accepted same name without returning OT_ERROR_ALREADY"); + + SuccessOrQuit(networkName.Set(Mac::NetworkName::Data(kName2, sizeof(kName2))), "NetworkName::Set() failed\n"); + CompareNetworkName(networkName, kName2); + + SuccessOrQuit(networkName.Set(Mac::NetworkName::Data(kEmptyName, 0)), "NetworkName::Set() failed\n"); + CompareNetworkName(networkName, kEmptyName); + + SuccessOrQuit(networkName.Set(Mac::NetworkName::Data(kLongName, sizeof(kLongName))), "NetworkName::Set() failed\n"); + CompareNetworkName(networkName, kLongName); + + VerifyOrQuit(networkName.Set(Mac::NetworkName::Data(kLongName, sizeof(kLongName) - 1)) == OT_ERROR_ALREADY, + "NetworkName::Set() accepted same name without returning OT_ERROR_ALREADY"); + + SuccessOrQuit(networkName.Set(Mac::NetworkName::Data(NULL, 0)), "NetworkName::Set() failed\n"); + CompareNetworkName(networkName, kEmptyName); + + SuccessOrQuit(networkName.Set(Mac::NetworkName::Data(kName1, sizeof(kName1))), "NetworkName::Set() failed\n"); + + VerifyOrQuit(networkName.Set(Mac::NetworkName::Data(kTooLongName, sizeof(kTooLongName))) == OT_ERROR_INVALID_ARGS, + "NetworkName::Set() accepted an invalid (too long) name\n"); + + CompareNetworkName(networkName, kName1); + + memset(buffer, 'a', sizeof(buffer)); + len = networkName.GetAsData().CopyTo(buffer, 1); + VerifyOrQuit(len == 1, "NetworkName::Data::CopyTo() failed\n"); + VerifyOrQuit(buffer[0] == kName1[0], "NetworkName::Data::CopyTo() failed\n"); + VerifyOrQuit(buffer[1] == 'a', "NetworkName::Data::CopyTo() failed\n"); + + memset(buffer, 'a', sizeof(buffer)); + len = networkName.GetAsData().CopyTo(buffer, sizeof(kName1) - 1); + VerifyOrQuit(len == sizeof(kName1) - 1, "NetworkName::Data::CopyTo() failed\n"); + VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NetworkName::Data::CopyTo() failed\n"); + VerifyOrQuit(buffer[sizeof(kName1)] == 'a', "NetworkName::Data::CopyTo() failed\n"); + + memset(buffer, 'a', sizeof(buffer)); + len = networkName.GetAsData().CopyTo(buffer, sizeof(buffer)); + VerifyOrQuit(len == sizeof(kName1) - 1, "NetworkName::Data::CopyTo() failed\n"); + VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NetworkName::Data::CopyTo() failed\n"); + VerifyOrQuit(buffer[sizeof(kName1)] == 0, "NetworkName::Data::CopyTo() failed\n"); +} + void TestMacHeader(void) { static const struct @@ -336,6 +412,7 @@ void TestMacChannelMask(void) int main(void) { ot::TestMacAddress(); + ot::TestMacNetworkName(); ot::TestMacHeader(); ot::TestMacChannelMask(); printf("All tests passed\n");