| /* |
| * 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 <openthread/ip6.h> |
| #include <openthread/srp_server.h> |
| |
| #include "common/array.hpp" |
| #include "common/as_core_type.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/numeric_limits.hpp" |
| #include "common/retain_ptr.hpp" |
| #include "common/timer.hpp" |
| #include "crypto/ecdsa.hpp" |
| #include "net/dns_types.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 |
| |
| namespace Srp { |
| |
| /** |
| * This class implements the SRP server. |
| * |
| */ |
| class Server : public InstanceLocator, private NonCopyable |
| { |
| friend class NetworkData::Publisher; |
| friend class UpdateMetadata; |
| friend class Service; |
| friend class Host; |
| friend class Dns::ServiceDiscovery::Server; |
| |
| enum RetainName : bool |
| { |
| kDeleteName = false, |
| kRetainName = true, |
| }; |
| |
| enum NotifyMode : bool |
| { |
| kDoNotNotifyServiceHandler = false, |
| kNotifyServiceHandler = true, |
| }; |
| |
| 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; |
| |
| /** |
| * This enumeration 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 address mode. |
| kAddressModeAnycast = OT_SRP_SERVER_ADDRESS_MODE_ANYCAST, ///< Anycast address mode. |
| }; |
| |
| class Host; |
| |
| enum State : uint8_t |
| { |
| kStateDisabled = OT_SRP_SERVER_STATE_DISABLED, |
| kStateRunning = OT_SRP_SERVER_STATE_RUNNING, |
| kStateStopped = OT_SRP_SERVER_STATE_STOPPED, |
| }; |
| |
| /** |
| * This class implements a server-side SRP service. |
| * |
| */ |
| class Service : public otSrpServerService, |
| public LinkedListEntry<Service>, |
| private Heap::Allocatable<Service>, |
| private NonCopyable |
| { |
| friend class Server; |
| friend class LinkedList<Service>; |
| friend class LinkedListEntry<Service>; |
| friend class Heap::Allocatable<Service>; |
| |
| public: |
| /** |
| * This type represents the flags which indicates which services to include or exclude when searching in (or |
| * iterating over) the list of SRP services. |
| * |
| */ |
| typedef otSrpServerServiceFlags Flags; |
| |
| /** |
| * This `Flags` constant indicates to include base services (not a sub-type). |
| * |
| */ |
| static constexpr Flags kFlagBaseType = OT_SRP_SERVER_SERVICE_FLAG_BASE_TYPE; |
| |
| /** |
| * This `Flags` constant indicates to include sub-type services. |
| * |
| */ |
| static constexpr Flags kFlagSubType = OT_SRP_SERVER_SERVICE_FLAG_SUB_TYPE; |
| |
| /** |
| * This `Flags` constant indicates to include active (not deleted) services. |
| * |
| */ |
| static constexpr Flags kFlagActive = OT_SRP_SERVER_SERVICE_FLAG_ACTIVE; |
| |
| /** |
| * This `Flags` constant indicates to include deleted services. |
| * |
| */ |
| static constexpr Flags kFlagDeleted = OT_SRP_SERVER_SERVICE_FLAG_DELETED; |
| |
| /** |
| * This method 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; } |
| |
| /** |
| * This method indicates whether the SRP service is a sub-type. |
| * |
| * @retval TRUE If the service is a sub-type. |
| * @retval FALSE If the service is not a sub-type. |
| * |
| */ |
| bool IsSubType(void) const { return mIsSubType; } |
| |
| /** |
| * This method 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 mDescription->mInstanceName.AsCString(); } |
| |
| /** |
| * This method 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(); } |
| |
| /** |
| * This method gets the sub-type label from service name. |
| * |
| * The full service name for a sub-type service follows "<sub-label>._sub.<service-labels>.<domain>.". This |
| * method copies the `<sub-label>` into the @p aLabel buffer. |
| * |
| * The @p aLabel is ensured to always be null-terminated after returning even in case of failure. |
| * |
| * @param[out] aLabel A pointer to a buffer to copy the sub-type label name. |
| * @param[in] aMaxSize Maximum size of @p aLabel buffer. |
| * |
| * @retval kErrorNone @p aLabel was updated successfully. |
| * @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 SRP service is not a sub-type. |
| * |
| */ |
| Error GetServiceSubTypeLabel(char *aLabel, uint8_t aMaxSize) const; |
| |
| /** |
| * This method returns the port of the service instance. |
| * |
| * @returns The port of the service. |
| * |
| */ |
| uint16_t GetPort(void) const { return mDescription->mPort; } |
| |
| /** |
| * This method returns the weight of the service instance. |
| * |
| * @returns The weight of the service. |
| * |
| */ |
| uint16_t GetWeight(void) const { return mDescription->mWeight; } |
| |
| /** |
| * This method returns the priority of the service instance. |
| * |
| * @returns The priority of the service. |
| * |
| */ |
| uint16_t GetPriority(void) const { return mDescription->mPriority; } |
| |
| /** |
| * This method 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 mDescription->mTxtData.GetBytes(); } |
| |
| /** |
| * This method 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 mDescription->mTxtData.GetLength(); } |
| |
| /** |
| * This method returns the host which the service instance reside on. |
| * |
| * @returns A reference to the host instance. |
| * |
| */ |
| const Host &GetHost(void) const { return *mDescription->mHost; } |
| |
| /** |
| * This method returns the expire time (in milliseconds) of the service. |
| * |
| * @returns The service expire time in milliseconds. |
| * |
| */ |
| TimeMilli GetExpireTime(void) const; |
| |
| /** |
| * This method returns the key expire time (in milliseconds) of the service. |
| * |
| * @returns The service key expire time in milliseconds. |
| * |
| */ |
| TimeMilli GetKeyExpireTime(void) const; |
| |
| /** |
| * This method 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; |
| |
| /** |
| * This method 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: |
| struct Description : public LinkedListEntry<Description>, |
| public Heap::Allocatable<Description>, |
| public RetainCountable, |
| private NonCopyable |
| { |
| Error Init(const char *aInstanceName, Host &aHost); |
| const char *GetInstanceName(void) const { return mInstanceName.AsCString(); } |
| bool Matches(const char *aInstanceName) const; |
| void ClearResources(void); |
| void TakeResourcesFrom(Description &aDescription); |
| Error SetTxtDataFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength); |
| |
| Description *mNext; |
| Heap::String mInstanceName; |
| Host * mHost; |
| Heap::Data mTxtData; |
| uint16_t mPriority; |
| uint16_t mWeight; |
| uint16_t mPort; |
| uint32_t mLease; // The LEASE time in seconds. |
| uint32_t mKeyLease; // The KEY-LEASE time in seconds. |
| TimeMilli mUpdateTime; |
| }; |
| |
| enum Action : uint8_t |
| { |
| kAddNew, |
| kUpdateExisting, |
| kRemoveButRetainName, |
| kFullyRemove, |
| kLeaseExpired, |
| kKeyLeaseExpired, |
| }; |
| |
| Error Init(const char *aServiceName, Description &aDescription, bool aIsSubType, TimeMilli aUpdateTime); |
| bool MatchesFlags(Flags aFlags) const; |
| const TimeMilli &GetUpdateTime(void) const { return mUpdateTime; } |
| void Log(Action aAction) const; |
| |
| Heap::String mServiceName; |
| RetainPtr<Description> mDescription; |
| Service * mNext; |
| TimeMilli mUpdateTime; |
| bool mIsDeleted : 1; |
| bool mIsSubType : 1; |
| bool mIsCommitted : 1; |
| }; |
| |
| /** |
| * This class implements the Host which registers services on the SRP server. |
| * |
| */ |
| class Host : public otSrpServerHost, |
| public InstanceLocator, |
| public LinkedListEntry<Host>, |
| private Heap::Allocatable<Host>, |
| private NonCopyable |
| { |
| friend class Server; |
| friend class LinkedListEntry<Host>; |
| friend class Heap::Allocatable<Host>; |
| |
| public: |
| /** |
| * This method 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); } |
| |
| /** |
| * This method 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(); } |
| |
| /** |
| * This method 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 = static_cast<uint8_t>(OT_MIN(mAddresses.GetLength(), NumericLimits<uint8_t>::kMax)); |
| return mAddresses.AsCArray(); |
| } |
| |
| /** |
| * This method returns the LEASE time of the host. |
| * |
| * @returns The LEASE time in seconds. |
| * |
| */ |
| uint32_t GetLease(void) const { return mLease; } |
| |
| /** |
| * This method 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; } |
| |
| /** |
| * This method returns the KEY resource record of the host. |
| * |
| * @returns A pointer to the ECDSA P 256 public key resource record |
| * if there is valid one. `nullptr` if no valid key exists. |
| * |
| */ |
| const Dns::Ecdsa256KeyRecord *GetKeyRecord(void) const { return mKeyRecord.IsValid() ? &mKeyRecord : nullptr; } |
| |
| /** |
| * This method returns the expire time (in milliseconds) of the host. |
| * |
| * @returns The expire time in milliseconds. |
| * |
| */ |
| TimeMilli GetExpireTime(void) const; |
| |
| /** |
| * This method 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; |
| |
| /** |
| * This method returns the `Service` linked list associated with the host. |
| * |
| * @returns The `Service` linked list. |
| * |
| */ |
| const LinkedList<Service> &GetServices(void) const { return mServices; } |
| |
| /** |
| * This method finds the next matching service on the host. |
| * |
| * @param[in] aPrevService A pointer to the previous service or `nullptr` to start from beginning of the list. |
| * @param[in] aFlags Flags indicating which services to include (base/sub-type, active/deleted). |
| * @param[in] aServiceName The service name to match. Set to `nullptr` to accept any name. |
| * @param[in] aInstanceName The service instance name to match. Set to `nullptr` to accept any name. |
| * |
| * @returns A pointer to the next matching service or `nullptr` if no matching service could be found. |
| * |
| */ |
| const Service *FindNextService(const Service *aPrevService, |
| Service::Flags aFlags = kFlagsAnyService, |
| const char * aServiceName = nullptr, |
| const char * aInstanceName = nullptr) const; |
| |
| /** |
| * This method 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 SetKeyRecord(Dns::Ecdsa256KeyRecord &aKeyRecord); |
| void SetLease(uint32_t aLease) { mLease = aLease; } |
| void SetKeyLease(uint32_t aKeyLease) { mKeyLease = aKeyLease; } |
| LinkedList<Service> &GetServices(void) { return mServices; } |
| Service * AddNewService(const char *aServiceName, |
| const char *aInstanceName, |
| bool aIsSubType, |
| TimeMilli aUpdateTime); |
| void RemoveService(Service *aService, RetainName aRetainName, NotifyMode aNotifyServiceHandler); |
| void FreeAllServices(void); |
| void ClearResources(void); |
| Error MergeServicesAndResourcesFrom(Host &aHost); |
| Error AddIp6Address(const Ip6::Address &aIp6Address); |
| bool HasServiceInstance(const char *aInstanceName) const; |
| RetainPtr<Service::Description> FindServiceDescription(const char *aInstanceName); |
| const RetainPtr<Service::Description> FindServiceDescription(const char *aInstanceName) const; |
| Service * FindService(const char *aServiceName, const char *aInstanceName); |
| const Service * FindService(const char *aServiceName, const char *aInstanceName) const; |
| |
| Host * mNext; |
| Heap::String mFullName; |
| Heap::Array<Ip6::Address> mAddresses; |
| |
| // TODO(wgtdkp): there is no necessary to save the entire resource |
| // record, saving only the ECDSA-256 public key should be enough. |
| Dns::Ecdsa256KeyRecord mKeyRecord; |
| uint32_t mLease; // The LEASE time in seconds. |
| uint32_t mKeyLease; // The KEY-LEASE time in seconds. |
| TimeMilli mUpdateTime; |
| LinkedList<Service> mServices; |
| }; |
| |
| /** |
| * This class handles LEASE and KEY-LEASE configurations. |
| * |
| */ |
| class LeaseConfig : public otSrpServerLeaseConfig |
| { |
| friend class Server; |
| |
| public: |
| /** |
| * This constructor 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; |
| }; |
| |
| /** |
| * This constant defines a `Service::Flags` combination accepting any service (base/sub-type, active/deleted). |
| * |
| */ |
| static constexpr Service::Flags kFlagsAnyService = OT_SRP_SERVER_FLAGS_ANY_SERVICE; |
| |
| /** |
| * This constant defines a `Service::Flags` combination accepting base services only. |
| * |
| */ |
| static constexpr Service::Flags kFlagsBaseTypeServiceOnly = OT_SRP_SERVER_FLAGS_BASE_TYPE_SERVICE_ONLY; |
| |
| /** |
| * This constant defines a `Service::Flags` combination accepting sub-type services only. |
| * |
| */ |
| static constexpr Service::Flags kFlagsSubTypeServiceOnly = OT_SRP_SERVER_FLAGS_SUB_TYPE_SERVICE_ONLY; |
| |
| /** |
| * This constant defines a `Service::Flags` combination accepting any active services (not deleted). |
| * |
| */ |
| static constexpr Service::Flags kFlagsAnyTypeActiveService = OT_SRP_SERVER_FLAGS_ANY_TYPE_ACTIVE_SERVICE; |
| |
| /** |
| * This constant defines a `Service::Flags` combination accepting any deleted services. |
| * |
| */ |
| static constexpr Service::Flags kFlagsAnyTypeDeletedService = OT_SRP_SERVER_FLAGS_ANY_TYPE_DELETED_SERVICE; |
| |
| /** |
| * This constructor initializes the SRP server object. |
| * |
| * @param[in] aInstance A reference to the OpenThread instance. |
| * |
| */ |
| explicit Server(Instance &aInstance); |
| |
| /** |
| * This method 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); |
| |
| /** |
| * This method 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(); } |
| |
| /** |
| * This method sets the domain on the SRP server. |
| * |
| * A trailing dot will be appended to @p aDomain if it is not already there. |
| * This method 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); |
| |
| /** |
| * This method returns the address mode being used by the SRP server. |
| * |
| * @returns The SRP server's address mode. |
| * |
| */ |
| AddressMode GetAddressMode(void) const { return mAddressMode; } |
| |
| /** |
| * This method 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); |
| |
| /** |
| * This method 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; } |
| |
| /** |
| * This method 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); |
| |
| /** |
| * This method tells whether the SRP server is currently running. |
| * |
| * @returns A boolean that indicates whether the server is running. |
| * |
| */ |
| bool IsRunning(void) const { return (mState == kStateRunning); } |
| |
| /** |
| * This method tells the state of the SRP server. |
| * |
| * @returns An enum that represents the state of the server. |
| * |
| */ |
| State GetState(void) const { return mState; } |
| |
| /** |
| * This method enables/disables the SRP server. |
| * |
| * @param[in] aEnabled A boolean to enable/disable the SRP server. |
| * |
| */ |
| void SetEnabled(bool aEnabled); |
| |
| /** |
| * This method returns the LEASE and KEY-LEASE configurations. |
| * |
| * @param[out] aLeaseConfig A reference to the `LeaseConfig` instance. |
| * |
| */ |
| void GetLeaseConfig(LeaseConfig &aLeaseConfig) const { aLeaseConfig = mLeaseConfig; } |
| |
| /** |
| * This method 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); |
| |
| /** |
| * This method 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); |
| |
| /** |
| * This method 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 uint16_t kUdpPayloadSize = Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header); |
| |
| static constexpr uint32_t kDefaultMinLease = 60u * 30; // 30 min (in seconds). |
| static constexpr uint32_t kDefaultMaxLease = 3600u * 2; // 2 hours (in seconds). |
| static constexpr uint32_t kDefaultMinKeyLease = 3600u * 24; // 1 day (in seconds). |
| static constexpr uint32_t kDefaultMaxKeyLease = 3600u * 24 * 14; // 14 days (in seconds). |
| static constexpr uint32_t kDefaultEventsHandlerTimeout = OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT; |
| |
| static constexpr AddressMode kDefaultAddressMode = |
| static_cast<AddressMode>(OPENTHREAD_CONFIG_SRP_SERVER_DEFAULT_ADDDRESS_MODE); |
| |
| static constexpr uint16_t kAnycastAddressModePort = 53; |
| |
| // Metdata 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; |
| 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<UpdateMetadata>, |
| public Heap::Allocatable<UpdateMetadata> |
| { |
| friend class LinkedListEntry<UpdateMetadata>; |
| friend class Heap::Allocatable<UpdateMetadata>; |
| |
| public: |
| TimeMilli GetExpireTime(void) const { return mExpireTime; } |
| const Dns::UpdateHeader &GetDnsHeader(void) const { return mDnsHeader; } |
| ServiceUpdateId GetId(void) const { return mId; } |
| const LeaseConfig & GetLeaseConfig(void) const { return mLeaseConfig; } |
| Host & GetHost(void) { return mHost; } |
| const Ip6::MessageInfo & GetMessageInfo(void) const { return mMessageInfo; } |
| 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. |
| 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. |
| bool mIsDirectRxFromClient; |
| }; |
| |
| void Start(void); |
| void Stop(void); |
| void SelectPort(void); |
| void PrepareSocket(void); |
| Ip6::Udp::Socket &GetSocket(void); |
| |
| #if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE |
| void HandleDnssdServerStateChange(void); |
| Error HandleDnssdServerUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); |
| #endif |
| |
| void HandleNetDataPublisherEvent(NetworkData::Publisher::Event aEvent); |
| |
| ServiceUpdateId AllocateId(void) { return mServiceUpdateId++; } |
| |
| void CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata); |
| void CommitSrpUpdate(Error aError, UpdateMetadata &aUpdateMetadata); |
| void CommitSrpUpdate(Error aError, |
| Host & aHost, |
| const Dns::UpdateHeader &aDnsHeader, |
| const Ip6::MessageInfo * aMessageInfo, |
| const LeaseConfig & aLeaseConfig); |
| Error ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); |
| Error ProcessMessage(Message & aMessage, |
| TimeMilli aRxTime, |
| 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 Dns::Ecdsa256KeyRecord &aKeyRecord, |
| 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 AddHost(Host &aHost); |
| void RemoveHost(Host *aHost, RetainName aRetainName, NotifyMode aNotifyServiceHandler); |
| 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, |
| const Ip6::MessageInfo & aMessageInfo); |
| static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); |
| void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); |
| static void HandleLeaseTimer(Timer &aTimer); |
| void HandleLeaseTimer(void); |
| static void HandleOutstandingUpdatesTimer(Timer &aTimer); |
| void HandleOutstandingUpdatesTimer(void); |
| |
| void HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError); |
| const UpdateMetadata *FindOutstandingUpdate(const MessageMetadata &aMessageMetadata) const; |
| static const char * AddressModeToString(AddressMode aMode); |
| |
| Ip6::Udp::Socket mSocket; |
| otSrpServerServiceUpdateHandler mServiceUpdateHandler; |
| void * mServiceUpdateHandlerContext; |
| |
| Heap::String mDomain; |
| |
| LeaseConfig mLeaseConfig; |
| |
| LinkedList<Host> mHosts; |
| TimerMilli mLeaseTimer; |
| |
| TimerMilli mOutstandingUpdatesTimer; |
| LinkedList<UpdateMetadata> mOutstandingUpdates; |
| |
| ServiceUpdateId mServiceUpdateId; |
| uint16_t mPort; |
| State mState; |
| AddressMode mAddressMode; |
| uint8_t mAnycastSequenceNumber; |
| bool mHasRegisteredAnyService : 1; |
| }; |
| |
| } // namespace Srp |
| |
| 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_ |