diff --git a/include/openthread/border_agent.h b/include/openthread/border_agent.h index e412f6d8e..cfbcb5646 100644 --- a/include/openthread/border_agent.h +++ b/include/openthread/border_agent.h @@ -57,6 +57,18 @@ extern "C" { */ #define OT_BORDER_AGENT_ID_LENGTH (16) +/** + * @struct otBorderAgentId + * + * This structure represents a Border Agent ID. + * + */ +OT_TOOL_PACKED_BEGIN +struct otBorderAgentId +{ + uint8_t mId[OT_BORDER_AGENT_ID_LENGTH]; +} OT_TOOL_PACKED_END; + /** * This enumeration defines the Border Agent state. * @@ -97,14 +109,32 @@ uint16_t otBorderAgentGetUdpPort(otInstance *aInstance); * * @param[in] aInstance A pointer to an OpenThread instance. * @param[out] aId A pointer to buffer to receive the ID. - * @param[inout] aLength Specifies the length of `aId` when used as input and receives the length - * actual ID data copied to `aId` when used as output. * - * @retval OT_ERROR_INVALID_ARGS If value of `aLength` if smaller than `OT_BORDER_AGENT_ID_LENGTH`. - * @retval OT_ERROR_NONE If successfully retrieved the Border Agent ID. + * @retval OT_ERROR_NONE If successfully retrieved the Border Agent ID. + * @retval ... If failed to retrieve the Border Agent ID. + * + * @sa otBorderAgentSetId * */ -otError otBorderAgentGetId(otInstance *aInstance, uint8_t *aId, uint16_t *aLength); +otError otBorderAgentGetId(otInstance *aInstance, otBorderAgentId *aId); + +/** + * Sets the Border Agent ID. + * + * The Border Agent ID will be saved in persistent storage and survive reboots. It's required to + * set the ID only once after factory reset. If the ID has never been set by calling this function, + * a random ID will be generated and returned when `otBorderAgentGetId` is called. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[out] aId A pointer to the Border Agent ID. + * + * @retval OT_ERROR_NONE If successfully set the Border Agent ID. + * @retval ... If failed to set the Border Agent ID. + * + * @sa otBorderAgentGetId + * + */ +otError otBorderAgentSetId(otInstance *aInstance, const otBorderAgentId *aId); /** * @} diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 3cb230a9b..6b7fe1b21 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (323) +#define OPENTHREAD_API_VERSION (324) /** * @addtogroup api-instance diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 133775e5a..0f6998034 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -545,11 +545,50 @@ template <> otError Interpreter::Process(Arg aArgs[]) OutputLine("%s", Stringify(otBorderAgentGetState(GetInstancePtr()), kStateStrings)); } +#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE + /** + * @cli ba id (get,set) + * @code + * ba id + * cb6da1e0c0448aaec39fa90f3d58f45c + * Done + * @endcode + * @code + * ba id 00112233445566778899aabbccddeeff + * Done + * @endcode + * @cparam ba id [@ca{border-agent-id}] + * Use the optional `border-agent-id` argument to set the Border Agent ID. + * @par + * Gets or sets the 16 bytes Border Router ID which can uniquely identifies the device among multiple BRs. + * @sa otBorderAgentGetId + * @sa otBorderAgentSetId + */ + else if (aArgs[0] == "id") + { + otBorderAgentId id; + + if (aArgs[1].IsEmpty()) + { + SuccessOrExit(error = otBorderAgentGetId(GetInstancePtr(), &id)); + OutputBytesLine(id.mId); + } + else + { + uint16_t idLength = sizeof(id); + + SuccessOrExit(error = aArgs[1].ParseAsHexString(idLength, id.mId)); + VerifyOrExit(idLength == sizeof(id), error = OT_ERROR_INVALID_ARGS); + error = otBorderAgentSetId(GetInstancePtr(), &id); + } + } +#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE else { - error = OT_ERROR_INVALID_COMMAND; + ExitNow(error = OT_ERROR_INVALID_COMMAND); } +exit: return error; } #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE diff --git a/src/core/api/border_agent_api.cpp b/src/core/api/border_agent_api.cpp index 70f39baef..35901162a 100644 --- a/src/core/api/border_agent_api.cpp +++ b/src/core/api/border_agent_api.cpp @@ -43,9 +43,14 @@ using namespace ot; #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE -otError otBorderAgentGetId(otInstance *aInstance, uint8_t *aId, uint16_t *aLength) +otError otBorderAgentGetId(otInstance *aInstance, otBorderAgentId *aId) { - return AsCoreType(aInstance).Get().GetId(aId, *aLength); + return AsCoreType(aInstance).Get().GetId(AsCoreType(aId)); +} + +otError otBorderAgentSetId(otInstance *aInstance, const otBorderAgentId *aId) +{ + return AsCoreType(aInstance).Get().SetId(AsCoreType(aId)); } #endif diff --git a/src/core/common/settings.cpp b/src/core/common/settings.cpp index 18f17d887..c9b6f3ad7 100644 --- a/src/core/common/settings.cpp +++ b/src/core/common/settings.cpp @@ -107,23 +107,12 @@ void SettingsBase::SrpServerInfo::Log(Action aAction) const #endif #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE -Error SettingsBase::BorderAgentId::SetId(const uint8_t *aId, uint16_t aLength) -{ - Error error = kErrorNone; - - VerifyOrExit(aLength == sizeof(mId), error = kErrorInvalidArgs); - memcpy(mId, aId, aLength); - -exit: - return error; -} - void SettingsBase::BorderAgentId::Log(Action aAction) const { char buffer[sizeof(BorderAgentId) * 2 + 1]; StringWriter sw(buffer, sizeof(buffer)); - sw.AppendHexBytes(GetId(), sizeof(BorderAgentId)); + sw.AppendHexBytes(GetId().mId, sizeof(BorderAgentId)); LogInfo("%s BorderAgentId {id:%s}", ActionToString(aAction), buffer); } #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE diff --git a/src/core/common/settings.hpp b/src/core/common/settings.hpp index 4b307d01c..ec32e2734 100644 --- a/src/core/common/settings.hpp +++ b/src/core/common/settings.hpp @@ -36,7 +36,6 @@ #include "openthread-core-config.h" -#include #include #include "common/clearable.hpp" @@ -48,6 +47,7 @@ #include "common/settings_driver.hpp" #include "crypto/ecdsa.hpp" #include "mac/mac_types.hpp" +#include "meshcop/border_agent.hpp" #include "meshcop/dataset.hpp" #include "net/ip6_address.hpp" #include "thread/version.hpp" @@ -773,20 +773,18 @@ public: * */ OT_TOOL_PACKED_BEGIN - class BorderAgentId : private Clearable + class BorderAgentId { friend class Settings; - friend class Clearable; public: - static constexpr Key kKey = kKeyBorderAgentId; ///< The associated key. - static constexpr uint8_t kLength = OT_BORDER_AGENT_ID_LENGTH; + static constexpr Key kKey = kKeyBorderAgentId; ///< The associated key. /** * This method initializes the `BorderAgentId` object. * */ - void Init(void) { Clear(); } + void Init(void) { mId = {}; } /** * This method returns the Border Agent ID. @@ -794,7 +792,7 @@ public: * @returns The Border Agent ID. * */ - const uint8_t *GetId(void) const { return mId; } + const MeshCoP::BorderAgent::Id &GetId(void) const { return mId; } /** * This method returns the Border Agent ID. @@ -802,21 +800,18 @@ public: * @returns The Border Agent ID. * */ - uint8_t *GetId(void) { return mId; } + MeshCoP::BorderAgent::Id &GetId(void) { return mId; } /** * This method sets the Border Agent ID. * - * @retval kErrorInvalidArgs If `aLength` doesn't equal to `OT_BORDER_AGENT_ID_LENGTH`. - * @retval kErrorNone If success. - * */ - Error SetId(const uint8_t *aId, uint16_t aLength); + void SetId(const MeshCoP::BorderAgent::Id &aId) { mId = aId; } private: void Log(Action aAction) const; - uint8_t mId[kLength]; + MeshCoP::BorderAgent::Id mId; } OT_TOOL_PACKED_END; #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp index 908175167..d15e77c21 100644 --- a/src/core/meshcop/border_agent.cpp +++ b/src/core/meshcop/border_agent.cpp @@ -41,6 +41,7 @@ #include "common/instance.hpp" #include "common/locator_getters.hpp" #include "common/log.hpp" +#include "common/settings.hpp" #include "meshcop/meshcop.hpp" #include "meshcop/meshcop_tlvs.hpp" #include "thread/thread_netif.hpp" @@ -233,29 +234,43 @@ BorderAgent::BorderAgent(Instance &aInstance) } #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE -Error BorderAgent::GetId(uint8_t *aId, uint16_t &aLength) +Error BorderAgent::GetId(Id &aId) { - Error error = kErrorNone; + Error error = kErrorNone; + Settings::BorderAgentId id; - VerifyOrExit(aLength >= sizeof(mId), error = kErrorInvalidArgs); VerifyOrExit(!mIdInitialized, error = kErrorNone); - if (Get().Read(mId) != kErrorNone) + if (Get().Read(id) != kErrorNone) { - Random::NonCrypto::FillBuffer(mId.GetId(), sizeof(mId)); - SuccessOrExit(error = Get().Save(mId)); + Random::NonCrypto::FillBuffer(id.GetId().mId, sizeof(id)); + SuccessOrExit(error = Get().Save(id)); } + mId = id.GetId(); mIdInitialized = true; exit: if (error == kErrorNone) { - memcpy(aId, mId.GetId(), sizeof(mId)); - aLength = static_cast(sizeof(mId)); + aId = mId; } return error; } + +Error BorderAgent::SetId(const Id &aId) +{ + Error error = kErrorNone; + Settings::BorderAgentId id; + + id.SetId(aId); + SuccessOrExit(error = Get().Save(id)); + mId = aId; + mIdInitialized = true; + +exit: + return error; +} #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE void BorderAgent::HandleNotifierEvents(Events aEvents) diff --git a/src/core/meshcop/border_agent.hpp b/src/core/meshcop/border_agent.hpp index 4a047a5e2..58f5b51a5 100644 --- a/src/core/meshcop/border_agent.hpp +++ b/src/core/meshcop/border_agent.hpp @@ -44,7 +44,6 @@ #include "common/locator.hpp" #include "common/non_copyable.hpp" #include "common/notifier.hpp" -#include "common/settings.hpp" #include "net/udp6.hpp" #include "thread/tmf.hpp" #include "thread/uri_paths.hpp" @@ -60,6 +59,8 @@ class BorderAgent : public InstanceLocator, private NonCopyable friend class Tmf::SecureAgent; public: + typedef otBorderAgentId Id; ///< Border Agent ID. + /** * This enumeration defines the Border Agent state. * @@ -87,15 +88,28 @@ public: * be published in the MeshCoP mDNS service as the `id` TXT value for the client to identify this * Border Router/Agent device. * - * @param[out] aId A pointer to buffer to receive the ID. - * @param[inout] aLength Specifies the length of `aId` when used as input and receives the length - * actual ID data copied to `aId` when used as output. + * @param[out] aId Reference to return the Border Agent ID. * - * @retval OT_ERROR_INVALID_ARGS If value of `aLength` if smaller than `OT_BORDER_AGENT_ID_LENGTH`. - * @retval OT_ERROR_NONE If successfully retrieved the Border Agent ID. + * @retval kErrorNone If successfully retrieved the Border Agent ID. + * @retval ... If failed to retrieve the Border Agent ID. * */ - Error GetId(uint8_t *aId, uint16_t &aLength); + Error GetId(Id &aId); + + /** + * Sets the Border Agent ID. + * + * The Border Agent ID will be saved in persistent storage and survive reboots. It's required + * to set the ID only once after factory reset. If the ID has never been set by calling this + * method, a random ID will be generated and returned when `GetId()` is called. + * + * @param[out] aId specifies the Border Agent ID. + * + * @retval kErrorNone If successfully set the Border Agent ID. + * @retval ... If failed to set the Border Agent ID. + * + */ + Error SetId(const Id &aId); #endif /** @@ -199,8 +213,8 @@ private: State mState; uint16_t mUdpProxyPort; #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE - Settings::BorderAgentId mId; - bool mIdInitialized; + Id mId; + bool mIdInitialized; #endif }; @@ -219,6 +233,7 @@ DeclareTmfHandler(BorderAgent, kUriProxyTx); } // namespace MeshCoP DefineMapEnum(otBorderAgentState, MeshCoP::BorderAgent::State); +DefineCoreType(otBorderAgentId, MeshCoP::BorderAgent::Id); } // namespace ot