/* * Copyright (c) 2020, 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 SRP server. */ #ifndef NET_SRP_SERVER_HPP_ #define NET_SRP_SERVER_HPP_ #include "openthread-core-config.h" #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE #if !OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE #error "OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE" #endif #if !OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE #error "OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE" #endif #if !OPENTHREAD_CONFIG_ECDSA_ENABLE #error "OPENTHREAD_CONFIG_ECDSA_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE" #endif #include #include #include "common/array.hpp" #include "common/as_core_type.hpp" #include "common/callback.hpp" #include "common/clearable.hpp" #include "common/heap.hpp" #include "common/heap_allocatable.hpp" #include "common/heap_array.hpp" #include "common/heap_data.hpp" #include "common/heap_string.hpp" #include "common/linked_list.hpp" #include "common/locator.hpp" #include "common/non_copyable.hpp" #include "common/notifier.hpp" #include "common/num_utils.hpp" #include "common/numeric_limits.hpp" #include "common/retain_ptr.hpp" #include "common/timer.hpp" #include "crypto/ecdsa.hpp" #include "net/dns_types.hpp" #include "net/dnssd.hpp" #include "net/ip6.hpp" #include "net/ip6_address.hpp" #include "net/udp6.hpp" #include "thread/network_data_publisher.hpp" struct otSrpServerHost { }; struct otSrpServerService { }; namespace ot { namespace Dns { namespace ServiceDiscovery { class Server; } } // namespace Dns #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE namespace BorderRouter { class RoutingManager; } #endif namespace Srp { class AdvertisingProxy; /** * Implements the SRP server. */ class Server : public InstanceLocator, private NonCopyable { friend class ot::Notifier; friend class NetworkData::Publisher; friend class UpdateMetadata; friend class Service; friend class Host; friend class Dns::ServiceDiscovery::Server; friend class AdvertisingProxy; #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE friend class BorderRouter::RoutingManager; #endif enum RetainName : bool { kDeleteName = false, kRetainName = true, }; enum NotifyMode : bool { kDoNotNotifyServiceHandler = false, kNotifyServiceHandler = true, }; #if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE static constexpr Dnssd::RequestId kInvalidRequestId = 0; #endif public: static constexpr uint16_t kUdpPortMin = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MIN; ///< The reserved min port. static constexpr uint16_t kUdpPortMax = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MAX; ///< The reserved max port. static_assert(kUdpPortMin <= kUdpPortMax, "invalid port range"); /** * The ID of SRP service update transaction. */ typedef otSrpServerServiceUpdateId ServiceUpdateId; /** * The SRP server lease information of a host/service. */ typedef otSrpServerLeaseInfo LeaseInfo; /** * Represents the address mode used by the SRP server. * * Address mode specifies how the address and port number are determined by the SRP server and how this info ins * published in the Thread Network Data. */ enum AddressMode : uint8_t { kAddressModeUnicast = OT_SRP_SERVER_ADDRESS_MODE_UNICAST, ///< Unicast mode with publisher. kAddressModeAnycast = OT_SRP_SERVER_ADDRESS_MODE_ANYCAST, ///< Anycast mode with publisher. kAddressModeUnicastForceAdd = OT_SRP_SERVER_ADDRESS_MODE_UNICAST_FORCE_ADD ///< Unicast - force add. }; class Host; /** * Represents the state of SRP server. */ enum State : uint8_t { kStateDisabled = OT_SRP_SERVER_STATE_DISABLED, ///< Server is disabled. kStateRunning = OT_SRP_SERVER_STATE_RUNNING, ///< Server is enabled and running. kStateStopped = OT_SRP_SERVER_STATE_STOPPED, ///< Server is enabled but stopped. }; /** * Implements a server-side SRP service. */ class Service : public otSrpServerService, public LinkedListEntry, private Heap::Allocatable, private NonCopyable { friend class Server; friend class LinkedList; friend class LinkedListEntry; friend class Heap::Allocatable; friend class AdvertisingProxy; public: /** * Tells if the SRP service has been deleted. * * A SRP service can be deleted but retains its name for future uses. * In this case, the service instance is not removed from the SRP server/registry. * It is guaranteed that all services are deleted if the host is deleted. * * @returns TRUE if the service has been deleted, FALSE if not. */ bool IsDeleted(void) const { return mIsDeleted; } /** * Gets the full service instance name of the service. * * @returns A pointer service instance name (as a null-terminated C string). */ const char *GetInstanceName(void) const { return mInstanceName.AsCString(); } /** * Gets the service instance label of the service. * * @returns A pointer service instance label (as a null-terminated C string). */ const char *GetInstanceLabel(void) const { return mInstanceLabel.AsCString(); } /** * Gets the full service name of the service. * * @returns A pointer service name (as a null-terminated C string). */ const char *GetServiceName(void) const { return mServiceName.AsCString(); } /** * Gets number of sub-types of this service. * * @returns The number of sub-types. */ uint16_t GetNumberOfSubTypes(void) const { return mSubTypes.GetLength(); } /** * Gets the sub-type service name (full name) at a given index. * * The full service name for a sub-type service follows "._sub...". * * @param[in] aIndex The index to get. * * @returns A pointer to sub-type service name at @p aIndex, or `nullptr` if none at this index. */ const char *GetSubTypeServiceNameAt(uint16_t aIndex) const; /** * Indicates whether or not service has a given sub-type. * * @param[in] aSubTypeServiceName The sub-type service name (full name). * * @retval TRUE Service contains the sub-type @p aSubTypeServiceName. * @retval FALSE Service does not contain the sub-type @p aSubTypeServiceName. */ bool HasSubTypeServiceName(const char *aSubTypeServiceName) const; /** * Parses a sub-type service name (full name) and extracts the sub-type label. * * The full service name for a sub-type service follows "._sub...". * * @param[in] aSubTypeServiceName A sub-type service name (full name). * @param[out] aLabel A pointer to a buffer to copy the extracted sub-type label. * @param[in] aLabelSize Maximum size of @p aLabel buffer. * * @retval kErrorNone Name was successfully parsed and @p aLabel was updated. * @retval kErrorNoBufs The sub-type label could not fit in @p aLabel buffer (number of chars from label * that could fit are copied in @p aLabel ensuring it is null-terminated). * @retval kErrorInvalidArgs @p aSubTypeServiceName is not a valid sub-type format. */ static Error ParseSubTypeServiceName(const char *aSubTypeServiceName, char *aLabel, uint8_t aLabelSize); /** * Returns the TTL of the service instance. * * @returns The TTL of the service instance. */ uint32_t GetTtl(void) const { return mTtl; } /** * Returns the port of the service instance. * * @returns The port of the service. */ uint16_t GetPort(void) const { return mPort; } /** * Returns the weight of the service instance. * * @returns The weight of the service. */ uint16_t GetWeight(void) const { return mWeight; } /** * Returns the priority of the service instance. * * @returns The priority of the service. */ uint16_t GetPriority(void) const { return mPriority; } /** * Returns the TXT record data of the service instance. * * @returns A pointer to the buffer containing the TXT record data. */ const uint8_t *GetTxtData(void) const { return mTxtData.GetBytes(); } /** * Returns the TXT record data length of the service instance. * * @return The TXT record data length (number of bytes in buffer returned from `GetTxtData()`). */ uint16_t GetTxtDataLength(void) const { return mTxtData.GetLength(); } /** * Returns the host which the service instance reside on. * * @returns A reference to the host instance. */ const Host &GetHost(void) const { return *mHost; } /** * Returns the LEASE time of the service. * * @returns The LEASE time in seconds. */ uint32_t GetLease(void) const { return mLease; } /** * Returns the KEY-LEASE time of the key of the service. * * @returns The KEY-LEASE time in seconds. */ uint32_t GetKeyLease(void) const { return mKeyLease; } /** * Returns the expire time (in milliseconds) of the service. * * @returns The service expire time in milliseconds. */ TimeMilli GetExpireTime(void) const; /** * Returns the key expire time (in milliseconds) of the service. * * @returns The service key expire time in milliseconds. */ TimeMilli GetKeyExpireTime(void) const; /** * Gets the LEASE and KEY-LEASE information of a given service. * * @param[out] aLeaseInfo A reference to a LeaseInfo instance. It contains the LEASE time, KEY-LEASE time, * remaining LEASE time and the remaining KEY-LEASE time. */ void GetLeaseInfo(LeaseInfo &aLeaseInfo) const; /** * Indicates whether this service matches a given service instance name. * * @param[in] aInstanceName The service instance name. * * @retval TRUE If the service matches the service instance name. * @retval FALSE If the service does not match the service instance name. */ bool MatchesInstanceName(const char *aInstanceName) const; /** * Tells whether this service matches a given service name. * * @param[in] aServiceName The full service name to match. * * @retval TRUE If the service matches the full service name. * @retval FALSE If the service does not match the full service name. */ bool MatchesServiceName(const char *aServiceName) const; private: enum Action : uint8_t { kAddNew, kUpdateExisting, kKeepUnchanged, kRemoveButRetainName, kFullyRemove, kLeaseExpired, kKeyLeaseExpired, }; Error Init(const char *aInstanceName, const char *aInstanceLabel, Host &aHost, TimeMilli aUpdateTime); Error SetTxtDataFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength); bool Matches(const char *aInstanceName) const; void Log(Action aAction) const; template static Error ParseSubTypeServiceName(const char *aSubTypeServiceName, char (&aLabel)[kLabelSize]) { return ParseSubTypeServiceName(aSubTypeServiceName, aLabel, kLabelSize); } Service *mNext; Heap::String mInstanceName; Heap::String mInstanceLabel; Heap::String mServiceName; Heap::Array mSubTypes; Host *mHost; Heap::Data mTxtData; uint16_t mPriority; uint16_t mWeight; uint16_t mPort; uint32_t mTtl; // In seconds uint32_t mLease; // In seconds uint32_t mKeyLease; // In seconds TimeMilli mUpdateTime; bool mIsDeleted : 1; bool mIsCommitted : 1; bool mParsedDeleteAllRrset : 1; bool mParsedSrv : 1; bool mParsedTxt : 1; #if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE bool mIsRegistered : 1; bool mIsKeyRegistered : 1; bool mIsReplaced : 1; bool mShouldAdvertise : 1; bool mShouldRegisterKey : 1; Dnssd::RequestId mAdvId; Dnssd::RequestId mKeyAdvId; #endif }; /** * Implements the Host which registers services on the SRP server. */ class Host : public otSrpServerHost, public InstanceLocator, public LinkedListEntry, private Heap::Allocatable, private NonCopyable { friend class Server; friend class LinkedListEntry; friend class Heap::Allocatable; friend class AdvertisingProxy; public: typedef Crypto::Ecdsa::P256::PublicKey Key; ///< Host key (public ECDSA P256 key). /** * Tells whether the Host object has been deleted. * * The Host object retains event if the host has been deleted by the SRP client, * because the host name may retain. * * @returns TRUE if the host is deleted, FALSE if the host is not deleted. */ bool IsDeleted(void) const { return (mLease == 0); } /** * Returns the full name of the host. * * @returns A pointer to the null-terminated full host name. */ const char *GetFullName(void) const { return mFullName.AsCString(); } /** * Returns addresses of the host. * * @param[out] aAddressesNum The number of the addresses. * * @returns A pointer to the addresses array or `nullptr` if no addresses. */ const Ip6::Address *GetAddresses(uint8_t &aAddressesNum) const { aAddressesNum = ClampToUint8(mAddresses.GetLength()); return mAddresses.AsCArray(); } /** * Returns the TTL of the host. * * @returns The TTL of the host. */ uint32_t GetTtl(void) const { return mTtl; } /** * Returns the LEASE time of the host. * * @returns The LEASE time in seconds. */ uint32_t GetLease(void) const { return mLease; } /** * Returns the KEY-LEASE time of the key of the host. * * @returns The KEY-LEASE time in seconds. */ uint32_t GetKeyLease(void) const { return mKeyLease; } /** * Gets the LEASE and KEY-LEASE information of a given host. * * @param[out] aLeaseInfo A reference to a LeaseInfo instance. It contains the LEASE time, KEY-LEASE time, * remaining LEASE time and the remaining KEY-LEASE time. */ void GetLeaseInfo(LeaseInfo &aLeaseInfo) const; /** * Returns the key associated with this host. * * @returns The host key. */ const Key &GetKey(void) const { return mKey; } /** * Returns the expire time (in milliseconds) of the host. * * @returns The expire time in milliseconds. */ TimeMilli GetExpireTime(void) const; /** * Returns the expire time (in milliseconds) of the key of the host. * * @returns The expire time of the key in milliseconds. */ TimeMilli GetKeyExpireTime(void) const; /** * Returns the `Service` linked list associated with the host. * * @returns The `Service` linked list. */ const LinkedList &GetServices(void) const { return mServices; } /* * Returns the next service. * * @param[in] aPrevService A pointer to the previous service or `nullptr` to start from beginning of the list. * * @returns A pointer to the next service or `nullptr` if no more services can be found. */ const Service *GetNextService(const Service *aPrevService) const; /** * Tells whether the host matches a given full name. * * @param[in] aFullName The full name. * * @returns A boolean that indicates whether the host matches the given name. */ bool Matches(const char *aFullName) const; private: Host(Instance &aInstance, TimeMilli aUpdateTime); ~Host(void); Error SetFullName(const char *aFullName); void SetTtl(uint32_t aTtl) { mTtl = aTtl; } void SetLease(uint32_t aLease) { mLease = aLease; } void SetKeyLease(uint32_t aKeyLease) { mKeyLease = aKeyLease; } void SetUseShortLeaseOption(bool aUse) { mUseShortLeaseOption = aUse; } bool ShouldUseShortLeaseOption(void) const { return mUseShortLeaseOption; } Error ProcessTtl(uint32_t aTtl); Service *AddNewService(const char *aInstanceName, const char *aInstanceLabel, TimeMilli aUpdateTime); void AddService(Service &aService); void RemoveService(Service *aService, RetainName aRetainName, NotifyMode aNotifyServiceHandler); bool HasService(const char *aInstanceName) const; Service *FindService(const char *aInstanceName); const Service *FindService(const char *aInstanceName) const; void FreeAllServices(void); void ClearResources(void); Error AddIp6Address(const Ip6::Address &aIp6Address); Host *mNext; Heap::String mFullName; Heap::Array mAddresses; Key mKey; uint32_t mTtl; // The TTL in seconds. uint32_t mLease; // The LEASE time in seconds. uint32_t mKeyLease; // The KEY-LEASE time in seconds. TimeMilli mUpdateTime; LinkedList mServices; bool mParsedKey : 1; bool mUseShortLeaseOption : 1; // Use short lease option (lease only 4 bytes). #if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE bool mIsRegistered : 1; bool mIsKeyRegistered : 1; bool mIsReplaced : 1; bool mShouldAdvertise : 1; bool mShouldRegisterKey : 1; Dnssd::RequestId mAdvId; Dnssd::RequestId mKeyAdvId; Dnssd::RequestIdRange mAdvIdRange; #endif }; /** * Handles TTL configuration. */ class TtlConfig : public otSrpServerTtlConfig { friend class Server; public: /** * Initializes to default TTL configuration. */ TtlConfig(void); private: bool IsValid(void) const { return mMinTtl <= mMaxTtl; } uint32_t GrantTtl(uint32_t aLease, uint32_t aTtl) const; }; /** * Handles LEASE and KEY-LEASE configurations. */ class LeaseConfig : public otSrpServerLeaseConfig { friend class Server; public: /** * Initialize to default LEASE and KEY-LEASE configurations. */ LeaseConfig(void); private: bool IsValid(void) const; uint32_t GrantLease(uint32_t aLease) const; uint32_t GrantKeyLease(uint32_t aKeyLease) const; }; /** * Initializes the SRP server object. * * @param[in] aInstance A reference to the OpenThread instance. */ explicit Server(Instance &aInstance); /** * Sets the SRP service events handler. * * @param[in] aServiceHandler A service events handler. * @param[in] aServiceHandlerContext A pointer to arbitrary context information. * * @note The handler SHOULD call HandleServiceUpdateResult to report the result of its processing. * Otherwise, a SRP update will be considered failed. * * @sa HandleServiceUpdateResult */ void SetServiceHandler(otSrpServerServiceUpdateHandler aServiceHandler, void *aServiceHandlerContext) { mServiceUpdateHandler.Set(aServiceHandler, aServiceHandlerContext); } /** * Returns the domain authorized to the SRP server. * * If the domain if not set by SetDomain, "default.service.arpa." will be returned. * A trailing dot is always appended even if the domain is set without it. * * @returns A pointer to the dot-joined domain string. */ const char *GetDomain(void) const { return mDomain.AsCString(); } /** * Sets the domain on the SRP server. * * A trailing dot will be appended to @p aDomain if it is not already there. * Should only be called before the SRP server is enabled. * * @param[in] aDomain The domain to be set. MUST NOT be `nullptr`. * * @retval kErrorNone Successfully set the domain to @p aDomain. * @retval kErrorInvalidState The SRP server is already enabled and the Domain cannot be changed. * @retval kErrorInvalidArgs The argument @p aDomain is not a valid DNS domain name. * @retval kErrorNoBufs There is no memory to store content of @p aDomain. */ Error SetDomain(const char *aDomain); /** * Returns the address mode being used by the SRP server. * * @returns The SRP server's address mode. */ AddressMode GetAddressMode(void) const { return mAddressMode; } /** * Sets the address mode to be used by the SRP server. * * @param[in] aMode The address mode to use. * * @retval kErrorNone Successfully set the address mode. * @retval kErrorInvalidState The SRP server is enabled and the address mode cannot be changed. */ Error SetAddressMode(AddressMode aMode); /** * Gets the sequence number used with anycast address mode. * * The sequence number is included in "DNS/SRP Service Anycast Address" entry published in the Network Data. * * @returns The anycast sequence number. */ uint8_t GetAnycastModeSequenceNumber(void) const { return mAnycastSequenceNumber; } /** * Sets the sequence number used with anycast address mode. * * @param[in] aSequenceNumber The sequence number to use. * * @retval kErrorNone Successfully set the address mode. * @retval kErrorInvalidState The SRP server is enabled and the sequence number cannot be changed. */ Error SetAnycastModeSequenceNumber(uint8_t aSequenceNumber); /** * Returns the state of the SRP server. * * @returns The state of the server. */ State GetState(void) const { return mState; } /** * Tells the port the SRP server is listening to. * * @returns The port of the server or 0 if the SRP server is not running. */ uint16_t GetPort(void) const { return (mState == kStateRunning) ? mPort : 0; } /** * Enables/disables the SRP server. * * @param[in] aEnabled A boolean to enable/disable the SRP server. */ void SetEnabled(bool aEnabled); #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE /** * Enables/disables the auto-enable mode on SRP server. * * When this mode is enabled, the Border Routing Manager controls if/when to enable or disable the SRP server. * SRP sever is auto-enabled if/when Border Routing is started it is done with the initial prefix and route * configurations (when the OMR and on-link prefixes are determined, advertised in emitted Router Advert message on * infrastructure side and published in the Thread Network Data). The SRP server is auto-disabled when BR is * stopped (e.g., if the infrastructure network interface is brought down or if BR gets detached). * * This mode can be disabled by a `SetAutoEnableMode(false)` call or if the SRP server is explicitly enabled or * disabled by a call to `SetEnabled()` method. Disabling auto-enable mode using `SetAutoEnableMode(false` call * will not change the current state of SRP sever (e.g., if it is enabled it stays enabled). * * @param[in] aEnabled A boolean to enable/disable the auto-enable mode. */ void SetAutoEnableMode(bool aEnabled); /** * Indicates whether the auto-enable mode is enabled or disabled. * * @retval TRUE The auto-enable mode is enabled. * @retval FALSE The auto-enable mode is disabled. */ bool IsAutoEnableMode(void) const { return mAutoEnable; } #endif #if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE /** * Enables the "Fast Start Mode" on the SRP server. * * The Fast Start Mode is designed for scenarios where a device, often a mobile device, needs to act as a * provisional SRP server (e.g., functioning as a temporary Border Router). The SRP server function is enabled only * if no other Border Routers (BRs) are already providing the SRP service within the Thread network. A common use * case is a mobile device joining a Thread network where it may be the first, or only, BR. Importantly, Fast * Start Mode allows the device to quickly start its SRP server functionality upon joining the network, allowing * other Thread devices to quickly connect and register their services without the typical delays associated with * standard Border Router initialization (and SRP server startup). * * Please refer to `otSrpServerEnableFastStartMode()` for more details. * * @retval kErrorNone Fast Start Mode was successfully enabled. * @retval kErrorInvalidState Cannot enable Fast Start Mode (e.g., already attached or server already enabled). */ Error EnableFastStartMode(void); /** * Indicates whether the Fast Start Mode is enabled or disabled. * * @retval TRUE The fast-start mode is enabled. * @retval FALSE The fast-start mode is disabled. */ bool IsFastStartModeEnabled(void) const { return mFastStartMode; } #endif /** * Returns the TTL configuration. * * @param[out] aTtlConfig A reference to the `TtlConfig` instance. */ void GetTtlConfig(TtlConfig &aTtlConfig) const { aTtlConfig = mTtlConfig; } /** * Sets the TTL configuration. * * @param[in] aTtlConfig A reference to the `TtlConfig` instance. * * @retval kErrorNone Successfully set the TTL configuration * @retval kErrorInvalidArgs The TTL range is not valid. */ Error SetTtlConfig(const TtlConfig &aTtlConfig); /** * Returns the LEASE and KEY-LEASE configurations. * * @param[out] aLeaseConfig A reference to the `LeaseConfig` instance. */ void GetLeaseConfig(LeaseConfig &aLeaseConfig) const { aLeaseConfig = mLeaseConfig; } /** * Sets the LEASE and KEY-LEASE configurations. * * When a LEASE time is requested from a client, the granted value will be * limited in range [aMinLease, aMaxLease]; and a KEY-LEASE will be granted * in range [aMinKeyLease, aMaxKeyLease]. * * @param[in] aLeaseConfig A reference to the `LeaseConfig` instance. * * @retval kErrorNone Successfully set the LEASE and KEY-LEASE ranges. * @retval kErrorInvalidArgs The LEASE or KEY-LEASE range is not valid. */ Error SetLeaseConfig(const LeaseConfig &aLeaseConfig); /** * Returns the `Host` linked list. * * @returns The `Host` linked list. */ const LinkedList &GetHosts(void) const { return mHosts; } /** * Returns the next registered SRP host. * * @param[in] aHost The current SRP host; use `nullptr` to get the first SRP host. * * @returns A pointer to the next SRP host or `nullptr` if no more SRP hosts can be found. */ const Host *GetNextHost(const Host *aHost); /** * Returns the response counters of the SRP server. * * @returns A pointer to the response counters of the SRP server. */ const otSrpServerResponseCounters *GetResponseCounters(void) const { return &mResponseCounters; } /** * Receives the service update result from service handler set by * SetServiceHandler. * * @param[in] aId The ID of the service update transaction. * @param[in] aError The service update result. */ void HandleServiceUpdateResult(ServiceUpdateId aId, Error aError); private: static constexpr uint8_t kSrpVersion = 0; static constexpr uint16_t kUdpPayloadSize = Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header); static constexpr uint32_t kDefaultMinLease = 30; // 30 seconds. static constexpr uint32_t kDefaultMaxLease = 27u * 3600; // 27 hours (in seconds). static constexpr uint32_t kDefaultMinKeyLease = 30; // 30 seconds. static constexpr uint32_t kDefaultMaxKeyLease = 189u * 3600; // 189 hours (in seconds). static constexpr uint32_t kDefaultMinTtl = kDefaultMinLease; static constexpr uint32_t kDefaultMaxTtl = kDefaultMaxLease; static constexpr uint32_t kDefaultEventsHandlerTimeout = OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT; static constexpr AddressMode kDefaultAddressMode = static_cast(OPENTHREAD_CONFIG_SRP_SERVER_DEFAULT_ADDRESS_MODE); static constexpr uint16_t kUninitializedPort = 0; static constexpr uint16_t kAnycastAddressModePort = 53; // Metadata for a received SRP Update message. struct MessageMetadata { // Indicates whether the `Message` is received directly from a // client or from an SRPL partner. bool IsDirectRxFromClient(void) const { return (mMessageInfo != nullptr); } Dns::UpdateHeader mDnsHeader; Dns::Zone mDnsZone; uint16_t mOffset; TimeMilli mRxTime; TtlConfig mTtlConfig; LeaseConfig mLeaseConfig; const Ip6::MessageInfo *mMessageInfo; // Set to `nullptr` when from SRPL. }; // This class includes metadata for processing a SRP update (register, deregister) // and sending DNS response to the client. class UpdateMetadata : public InstanceLocator, public LinkedListEntry, public Heap::Allocatable { friend class LinkedListEntry; friend class Heap::Allocatable; public: TimeMilli GetExpireTime(void) const { return mExpireTime; } const Dns::UpdateHeader &GetDnsHeader(void) const { return mDnsHeader; } ServiceUpdateId GetId(void) const { return mId; } const TtlConfig &GetTtlConfig(void) const { return mTtlConfig; } const LeaseConfig &GetLeaseConfig(void) const { return mLeaseConfig; } Host &GetHost(void) { return mHost; } const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; } Error GetError(void) const { return mError; } void SetError(Error aError) { mError = aError; } bool IsDirectRxFromClient(void) const { return mIsDirectRxFromClient; } bool Matches(ServiceUpdateId aId) const { return mId == aId; } private: UpdateMetadata(Instance &aInstance, Host &aHost, const MessageMetadata &aMessageMetadata); UpdateMetadata *mNext; TimeMilli mExpireTime; Dns::UpdateHeader mDnsHeader; ServiceUpdateId mId; // The ID of this service update transaction. TtlConfig mTtlConfig; // TTL config to use when processing the message. LeaseConfig mLeaseConfig; // Lease config to use when processing the message. Host &mHost; // The `UpdateMetadata` has no ownership of this host. Ip6::MessageInfo mMessageInfo; // Valid when `mIsDirectRxFromClient` is true. Error mError; bool mIsDirectRxFromClient; }; void Enable(void); void Disable(void); void Start(void); void Stop(void); void InitPort(void); void SelectPort(void); Error PrepareSocket(void); Ip6::Udp::Socket &GetSocket(void); LinkedList &GetHosts(void) { return mHosts; } #if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE void HandleDnssdServerStateChange(void); Error HandleDnssdServerUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); #endif #if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE void DisableFastStartMode(void); void HandleNotifierEvents(Events aEvents); bool NetDataContainsOtherSrpServers(void) const; #endif void HandleNetDataPublisherEvent(NetworkData::Publisher::Event aEvent); ServiceUpdateId AllocateServiceUpdateId(void) { return mServiceUpdateId++; } void InformUpdateHandlerOrCommit(Error aError, Host &aHost, const MessageMetadata &aMetadata); void CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata); void CommitSrpUpdate(UpdateMetadata &aUpdateMetadata); void CommitSrpUpdate(Error aError, Host &aHost, const Dns::UpdateHeader &aDnsHeader, const Ip6::MessageInfo *aMessageInfo, const TtlConfig &aTtlConfig, const LeaseConfig &aLeaseConfig); Error ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); Error ProcessMessage(Message &aMessage, TimeMilli aRxTime, const TtlConfig &aTtlConfig, const LeaseConfig &aLeaseConfig, const Ip6::MessageInfo *aMessageInfo); void ProcessDnsUpdate(Message &aMessage, MessageMetadata &aMetadata); Error ProcessUpdateSection(Host &aHost, const Message &aMessage, MessageMetadata &aMetadata) const; Error ProcessAdditionalSection(Host *aHost, const Message &aMessage, MessageMetadata &aMetadata) const; Error VerifySignature(const Host::Key &aKey, const Message &aMessage, Dns::UpdateHeader aDnsHeader, uint16_t aSigOffset, uint16_t aSigRdataOffset, uint16_t aSigRdataLength, const char *aSignerName) const; Error ProcessZoneSection(const Message &aMessage, MessageMetadata &aMetadata) const; Error ProcessHostDescriptionInstruction(Host &aHost, const Message &aMessage, const MessageMetadata &aMetadata) const; Error ProcessServiceDiscoveryInstructions(Host &aHost, const Message &aMessage, const MessageMetadata &aMetadata) const; Error ProcessServiceDescriptionInstructions(Host &aHost, const Message &aMessage, MessageMetadata &aMetadata) const; static bool IsValidDeleteAllRecord(const Dns::ResourceRecord &aRecord); void HandleUpdate(Host &aHost, const MessageMetadata &aMetadata); void RemoveHost(Host *aHost, RetainName aRetainName); bool HasNameConflictsWith(Host &aHost) const; void SendResponse(const Dns::UpdateHeader &aHeader, Dns::UpdateHeader::Response aResponseCode, const Ip6::MessageInfo &aMessageInfo); void SendResponse(const Dns::UpdateHeader &aHeader, uint32_t aLease, uint32_t aKeyLease, bool mUseShortLeaseOption, const Ip6::MessageInfo &aMessageInfo); void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); void HandleLeaseTimer(void); static void HandleOutstandingUpdatesTimer(Timer &aTimer); void HandleOutstandingUpdatesTimer(void); void ProcessCompletedUpdates(void); const UpdateMetadata *FindOutstandingUpdate(const MessageMetadata &aMessageMetadata) const; static const char *AddressModeToString(AddressMode aMode); void UpdateResponseCounters(Dns::Header::Response aResponseCode); void UpdateAddrResolverCacheTable(const Ip6::MessageInfo &aMessageInfo, const Host &aHost); using LeaseTimer = TimerMilliIn; using UpdateTimer = TimerMilliIn; using CompletedUpdatesTask = TaskletIn; using ServerSocket = Ip6::Udp::SocketIn; ServerSocket mSocket; Callback mServiceUpdateHandler; Heap::String mDomain; TtlConfig mTtlConfig; LeaseConfig mLeaseConfig; LinkedList mHosts; LeaseTimer mLeaseTimer; UpdateTimer mOutstandingUpdatesTimer; LinkedList mOutstandingUpdates; LinkedList mCompletedUpdates; CompletedUpdatesTask mCompletedUpdateTask; ServiceUpdateId mServiceUpdateId; uint16_t mPort; State mState; AddressMode mAddressMode; uint8_t mAnycastSequenceNumber; bool mHasRegisteredAnyService : 1; #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE bool mAutoEnable : 1; #endif #if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE bool mFastStartMode : 1; AddressMode mPrevAddressMode; #endif otSrpServerResponseCounters mResponseCounters; }; } // namespace Srp DefineCoreType(otSrpServerTtlConfig, Srp::Server::TtlConfig); DefineCoreType(otSrpServerLeaseConfig, Srp::Server::LeaseConfig); DefineCoreType(otSrpServerHost, Srp::Server::Host); DefineCoreType(otSrpServerService, Srp::Server::Service); DefineMapEnum(otSrpServerState, Srp::Server::State); DefineMapEnum(otSrpServerAddressMode, Srp::Server::AddressMode); } // namespace ot #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE #endif // NET_SRP_SERVER_HPP_