1 /*
2  *  Copyright (c) 2020, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for SRP server.
32  */
33 
34 #ifndef NET_SRP_SERVER_HPP_
35 #define NET_SRP_SERVER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
40 
41 #if !OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
42 #error "OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
43 #endif
44 
45 #if !OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
46 #error "OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
47 #endif
48 
49 #if !OPENTHREAD_CONFIG_ECDSA_ENABLE
50 #error "OPENTHREAD_CONFIG_ECDSA_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
51 #endif
52 
53 #include <openthread/ip6.h>
54 #include <openthread/srp_server.h>
55 
56 #include "common/clearable.hpp"
57 #include "common/heap_string.hpp"
58 #include "common/linked_list.hpp"
59 #include "common/locator.hpp"
60 #include "common/non_copyable.hpp"
61 #include "common/notifier.hpp"
62 #include "common/timer.hpp"
63 #include "crypto/ecdsa.hpp"
64 #include "net/dns_types.hpp"
65 #include "net/ip6.hpp"
66 #include "net/ip6_address.hpp"
67 #include "net/udp6.hpp"
68 #include "thread/network_data_publisher.hpp"
69 
70 namespace ot {
71 namespace Srp {
72 
73 /**
74  * This class implements the SRP server.
75  *
76  */
77 class Server : public InstanceLocator, private NonCopyable
78 {
79     friend class NetworkData::Publisher;
80     friend class UpdateMetadata;
81     friend class Service;
82     friend class Host;
83 
84 public:
85     static constexpr uint16_t kUdpPortMin = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MIN; ///< The reserved min port.
86     static constexpr uint16_t kUdpPortMax = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MAX; ///< The reserved max port.
87 
88     static_assert(kUdpPortMin <= kUdpPortMax, "invalid port range");
89 
90     /**
91      * The ID of SRP service update transaction.
92      *
93      */
94     typedef otSrpServerServiceUpdateId ServiceUpdateId;
95 
96     class Host;
97 
98     enum State : uint8_t
99     {
100         kStateDisabled = OT_SRP_SERVER_STATE_DISABLED,
101         kStateRunning  = OT_SRP_SERVER_STATE_RUNNING,
102         kStateStopped  = OT_SRP_SERVER_STATE_STOPPED,
103     };
104 
105     /**
106      * This class implements a server-side SRP service.
107      *
108      */
109     class Service : public LinkedListEntry<Service>, private NonCopyable
110     {
111         friend class Server;
112         friend class LinkedList<Service>;
113         friend class LinkedListEntry<Service>;
114 
115     public:
116         /**
117          * This type represents the flags which indicates which services to include or exclude when searching in (or
118          * iterating over) the list of SRP services.
119          *
120          */
121         typedef otSrpServerServiceFlags Flags;
122 
123         /**
124          * This `Flags` constant indicates to include base services (not a sub-type).
125          *
126          */
127         static constexpr Flags kFlagBaseType = OT_SRP_SERVER_SERVICE_FLAG_BASE_TYPE;
128 
129         /**
130          * This `Flags` constant indicates to include sub-type services.
131          *
132          */
133         static constexpr Flags kFlagSubType = OT_SRP_SERVER_SERVICE_FLAG_SUB_TYPE;
134 
135         /**
136          * This `Flags` constant indicates to include active (not deleted) services.
137          *
138          */
139         static constexpr Flags kFlagActive = OT_SRP_SERVER_SERVICE_FLAG_ACTIVE;
140 
141         /**
142          * This `Flags` constant indicates to include deleted services.
143          *
144          */
145         static constexpr Flags kFlagDeleted = OT_SRP_SERVER_SERVICE_FLAG_DELETED;
146 
147         /**
148          * This method tells if the SRP service has been deleted.
149          *
150          * A SRP service can be deleted but retains its name for future uses.
151          * In this case, the service instance is not removed from the SRP server/registry.
152          * It is guaranteed that all services are deleted if the host is deleted.
153          *
154          * @returns  TRUE if the service has been deleted, FALSE if not.
155          *
156          */
IsDeleted(void) const157         bool IsDeleted(void) const { return mIsDeleted; }
158 
159         /**
160          * This method indicates whether the SRP service is a sub-type.
161          *
162          * @retval TRUE    If the service is a sub-type.
163          * @retval FALSE   If the service is not a sub-type.
164          *
165          */
IsSubType(void) const166         bool IsSubType(void) const { return mIsSubType; }
167 
168         /**
169          * This method gets the full service instance name of the service.
170          *
171          * @returns  A pointer service instance name (as a null-terminated C string).
172          *
173          */
GetInstanceName(void) const174         const char *GetInstanceName(void) const { return mDescription.mInstanceName.AsCString(); }
175 
176         /**
177          * This method gets the full service name of the service.
178          *
179          * @returns  A pointer service name (as a null-terminated C string).
180          *
181          */
GetServiceName(void) const182         const char *GetServiceName(void) const { return mServiceName.AsCString(); }
183 
184         /**
185          * This method gets the sub-type label from service name.
186          *
187          * The full service name for a sub-type service follows "<sub-label>._sub.<service-labels>.<domain>.". This
188          * method copies the `<sub-label>` into the @p aLabel buffer.
189          *
190          * The @p aLabel is ensured to always be null-terminated after returning even in case of failure.
191          *
192          * @param[out] aLabel        A pointer to a buffer to copy the sub-type label name.
193          * @param[in]  aMaxSize      Maximum size of @p aLabel buffer.
194          *
195          * @retval kErrorNone         @p aLabel was updated successfully.
196          * @retval kErrorNoBufs       The sub-type label could not fit in @p aLabel buffer (number of chars from label
197          *                            that could fit are copied in @p aLabel ensuring it is null-terminated).
198          * @retval kErrorInvalidArgs  SRP service is not a sub-type.
199          *
200          */
201         Error GetServiceSubTypeLabel(char *aLabel, uint8_t aMaxSize) const;
202 
203         /**
204          * This method returns the port of the service instance.
205          *
206          * @returns  The port of the service.
207          *
208          */
GetPort(void) const209         uint16_t GetPort(void) const { return mDescription.mPort; }
210 
211         /**
212          * This method returns the weight of the service instance.
213          *
214          * @returns  The weight of the service.
215          *
216          */
GetWeight(void) const217         uint16_t GetWeight(void) const { return mDescription.mWeight; }
218 
219         /**
220          * This method returns the priority of the service instance.
221          *
222          * @param[in]  aService  A pointer to the SRP service.
223          *
224          * @returns  The priority of the service.
225          *
226          */
GetPriority(void) const227         uint16_t GetPriority(void) const { return mDescription.mPriority; }
228 
229         /**
230          * This method returns the TXT record data of the service instance.
231          *
232          * @returns A pointer to the buffer containing the TXT record data.
233          *
234          */
GetTxtData(void) const235         const uint8_t *GetTxtData(void) const { return mDescription.mTxtData; }
236 
237         /**
238          * This method returns the TXT record data length of the service instance.
239          *
240          * @return The TXT record data length (number of bytes in buffer returned from `GetTxtData()`).
241          *
242          */
GetTxtDataLength(void) const243         uint16_t GetTxtDataLength(void) const { return mDescription.mTxtLength; }
244 
245         /**
246          * This method returns the host which the service instance reside on.
247          *
248          * @returns  A reference to the host instance.
249          *
250          */
GetHost(void) const251         const Host &GetHost(void) const { return mDescription.mHost; }
252 
253         /**
254          * This method returns the expire time (in milliseconds) of the service.
255          *
256          * @returns  The service expire time in milliseconds.
257          *
258          */
259         TimeMilli GetExpireTime(void) const;
260 
261         /**
262          * This method returns the key expire time (in milliseconds) of the service.
263          *
264          * @returns  The service key expire time in milliseconds.
265          *
266          */
267         TimeMilli GetKeyExpireTime(void) const;
268 
269         /**
270          * This method indicates whether this service matches a given service instance name.
271          *
272          * @param[in]  aInstanceName  The service instance name.
273          *
274          * @retval  TRUE   If the service matches the service instance name.
275          * @retval  FALSE  If the service does not match the service instance name.
276          *
277          */
MatchesInstanceName(const char * aInstanceName) const278         bool MatchesInstanceName(const char *aInstanceName) const
279         {
280             return (mDescription.mInstanceName == aInstanceName);
281         }
282 
283         /**
284          * This method tells whether this service matches a given service name.
285          *
286          * @param[in] aServiceName  The full service name to match.
287          *
288          * @retval  TRUE   If the service matches the full service name.
289          * @retval  FALSE  If the service does not match the full service name.
290          *
291          */
MatchesServiceName(const char * aServiceName) const292         bool MatchesServiceName(const char *aServiceName) const { return (mServiceName == aServiceName); }
293 
294     private:
295         struct Description : public LinkedListEntry<Description>, private NonCopyable
296         {
297             static Description *New(const char *aInstanceName, Host &aHost);
298 
299             explicit Description(Host &aHost);
300             void        Free(void);
GetInstanceNameot::Srp::Server::Service::Description301             const char *GetInstanceName(void) const { return mInstanceName.AsCString(); }
Matchesot::Srp::Server::Service::Description302             bool        Matches(const char *aInstanceName) const { return (mInstanceName == aInstanceName); }
303             void        ClearResources(void);
304             void        TakeResourcesFrom(Description &aDescription);
305             Error       SetTxtDataFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
306 
307             Description *mNext;
308             HeapString   mInstanceName;
309             Host &       mHost;
310             uint16_t     mPriority;
311             uint16_t     mWeight;
312             uint16_t     mPort;
313             uint16_t     mTxtLength;
314             uint8_t *    mTxtData;
315             uint32_t     mLease;    // The LEASE time in seconds.
316             uint32_t     mKeyLease; // The KEY-LEASE time in seconds.
317             TimeMilli    mTimeLastUpdate;
318         };
319 
320         enum Action : uint8_t
321         {
322             kAddNew,
323             kUpdateExisting,
324             kRemoveButRetainName,
325             kFullyRemove,
326             kLeaseExpired,
327             kKeyLeaseExpired,
328         };
329 
330         static Service *New(const char *aServiceName, Description &aDescription, bool aIsSubType);
331 
332         Service(Description &aDescription, bool aIsSubType);
333 
334         void Free(void);
335         bool MatchesFlags(Flags aFlags) const;
336         void Log(Action aAction) const;
337 
338         HeapString   mServiceName;
339         Description &mDescription;
340         Service *    mNext;
341         TimeMilli    mTimeLastUpdate;
342         bool         mIsDeleted : 1;
343         bool         mIsSubType : 1;
344         bool         mIsCommitted : 1;
345     };
346 
347     /**
348      * This class implements the Host which registers services on the SRP server.
349      *
350      */
351     class Host : public LinkedListEntry<Host>, public InstanceLocator, private NonCopyable
352     {
353         friend class LinkedListEntry<Host>;
354         friend class Server;
355 
356     public:
357         /**
358          * This method tells whether the Host object has been deleted.
359          *
360          * The Host object retains event if the host has been deleted by the SRP client,
361          * because the host name may retain.
362          *
363          * @returns  TRUE if the host is deleted, FALSE if the host is not deleted.
364          *
365          */
IsDeleted(void) const366         bool IsDeleted(void) const { return (mLease == 0); }
367 
368         /**
369          * This method returns the full name of the host.
370          *
371          * @returns  A pointer to the null-terminated full host name.
372          *
373          */
GetFullName(void) const374         const char *GetFullName(void) const { return mFullName.AsCString(); }
375 
376         /**
377          * This method returns addresses of the host.
378          *
379          * @param[out]  aAddressesNum  The number of the addresses.
380          *
381          * @returns  A pointer to the addresses array.
382          *
383          */
GetAddresses(uint8_t & aAddressesNum) const384         const Ip6::Address *GetAddresses(uint8_t &aAddressesNum) const
385         {
386             aAddressesNum = mAddressesNum;
387             return mAddresses;
388         }
389 
390         /**
391          * This method returns the LEASE time of the host.
392          *
393          * @returns  The LEASE time in seconds.
394          *
395          */
GetLease(void) const396         uint32_t GetLease(void) const { return mLease; }
397 
398         /**
399          * This method returns the KEY-LEASE time of the key of the host.
400          *
401          * @returns  The KEY-LEASE time in seconds.
402          *
403          */
GetKeyLease(void) const404         uint32_t GetKeyLease(void) const { return mKeyLease; }
405 
406         /**
407          * This method returns the KEY resource of the host.
408          *
409          * @returns  A pointer to the ECDSA P 256 public key if there is valid one.
410          *           nullptr if no valid key exists.
411          *
412          */
GetKey(void) const413         const Dns::Ecdsa256KeyRecord *GetKey(void) const { return mKey.IsValid() ? &mKey : nullptr; }
414 
415         /**
416          * This method returns the expire time (in milliseconds) of the host.
417          *
418          * @returns  The expire time in milliseconds.
419          *
420          */
421         TimeMilli GetExpireTime(void) const;
422 
423         /**
424          * This method returns the expire time (in milliseconds) of the key of the host.
425          *
426          * @returns  The expire time of the key in milliseconds.
427          *
428          */
429         TimeMilli GetKeyExpireTime(void) const;
430 
431         /**
432          * This method returns the `Service` linked list associated with the host.
433          *
434          * @returns The `Service` linked list.
435          *
436          */
GetServices(void) const437         const LinkedList<Service> &GetServices(void) const { return mServices; }
438 
439         /**
440          * This method finds the next matching service on the host.
441          *
442          * @param[in] aPrevService   A pointer to the previous service or `nullptr` to start from beginning of the list.
443          * @param[in] aFlags         Flags indicating which services to include (base/sub-type, active/deleted).
444          * @param[in] aServiceName   The service name to match. Set to `nullptr` to accept any name.
445          * @param[in] aInstanceName  The service instance name to match. Set to `nullptr` to accept any name.
446          *
447          * @returns  A pointer to the next matching service or `nullptr` if no matching service could be found.
448          *
449          */
450         const Service *FindNextService(const Service *aPrevService,
451                                        Service::Flags aFlags        = kFlagsAnyService,
452                                        const char *   aServiceName  = nullptr,
453                                        const char *   aInstanceName = nullptr) const;
454 
455         /**
456          * This method tells whether the host matches a given full name.
457          *
458          * @param[in]  aFullName  The full name.
459          *
460          * @returns  A boolean that indicates whether the host matches the given name.
461          *
462          */
Matches(const char * aFullName) const463         bool Matches(const char *aFullName) const { return (mFullName == aFullName); }
464 
465     private:
466         static constexpr uint16_t kMaxAddressesNum = OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM;
467 
468         static Host *New(Instance &aInstance);
469 
470         explicit Host(Instance &aInstance);
471         void                        Free(void);
472         Error                       SetFullName(const char *aFullName);
473         void                        SetKey(Dns::Ecdsa256KeyRecord &aKey);
SetLease(uint32_t aLease)474         void                        SetLease(uint32_t aLease) { mLease = aLease; }
SetKeyLease(uint32_t aKeyLease)475         void                        SetKeyLease(uint32_t aKeyLease) { mKeyLease = aKeyLease; }
GetServices(void)476         LinkedList<Service> &       GetServices(void) { return mServices; }
477         Service *                   AddNewService(const char *aServiceName, const char *aInstanceName, bool aIsSubType);
478         void                        RemoveService(Service *aService, bool aRetainName, bool aNotifyServiceHandler);
479         void                        FreeAllServices(void);
480         void                        FreeUnusedServiceDescriptions(void);
481         void                        ClearResources(void);
482         Error                       MergeServicesAndResourcesFrom(Host &aHost);
483         Error                       AddIp6Address(const Ip6::Address &aIp6Address);
484         Service::Description *      FindServiceDescription(const char *aInstanceName);
485         const Service::Description *FindServiceDescription(const char *aInstanceName) const;
486         Service *                   FindService(const char *aServiceName, const char *aInstanceName);
487         const Service *             FindService(const char *aServiceName, const char *aInstanceName) const;
488 
489         HeapString   mFullName;
490         Ip6::Address mAddresses[kMaxAddressesNum];
491         uint8_t      mAddressesNum;
492         Host *       mNext;
493 
494         Dns::Ecdsa256KeyRecord           mKey;
495         uint32_t                         mLease;    // The LEASE time in seconds.
496         uint32_t                         mKeyLease; // The KEY-LEASE time in seconds.
497         TimeMilli                        mTimeLastUpdate;
498         LinkedList<Service>              mServices;
499         LinkedList<Service::Description> mServiceDescriptions;
500     };
501 
502     /**
503      * This class handles LEASE and KEY-LEASE configurations.
504      *
505      */
506     class LeaseConfig : public otSrpServerLeaseConfig
507     {
508         friend class Server;
509 
510     public:
511         /**
512          * This constructor initialize to default LEASE and KEY-LEASE configurations.
513          *
514          */
515         LeaseConfig(void);
516 
517     private:
518         bool     IsValid(void) const;
519         uint32_t GrantLease(uint32_t aLease) const;
520         uint32_t GrantKeyLease(uint32_t aKeyLease) const;
521     };
522 
523     /**
524      * This constant defines a `Service::Flags` combination accepting any service (base/sub-type, active/deleted).
525      *
526      */
527     static constexpr Service::Flags kFlagsAnyService = OT_SRP_SERVER_FLAGS_ANY_SERVICE;
528 
529     /**
530      * This constant defines a `Service::Flags` combination accepting base services only.
531      *
532      */
533     static constexpr Service::Flags kFlagsBaseTypeServiceOnly = OT_SRP_SERVER_FLAGS_BASE_TYPE_SERVICE_ONLY;
534 
535     /**
536      * This constant defines a `Service::Flags` combination accepting sub-type services only.
537      *
538      */
539     static constexpr Service::Flags kFlagsSubTypeServiceOnly = OT_SRP_SERVER_FLAGS_SUB_TYPE_SERVICE_ONLY;
540 
541     /**
542      * This constant defines a `Service::Flags` combination accepting any active services (not deleted).
543      *
544      */
545     static constexpr Service::Flags kFlagsAnyTypeActiveService = OT_SRP_SERVER_FLAGS_ANY_TYPE_ACTIVE_SERVICE;
546 
547     /**
548      * This constant defines a `Service::Flags` combination accepting any deleted services.
549      *
550      */
551     static constexpr Service::Flags kFlagsAnyTypeDeletedService = OT_SRP_SERVER_FLAGS_ANY_TYPE_DELETED_SERVICE;
552 
553     /**
554      * This constructor initializes the SRP server object.
555      *
556      * @param[in]  aInstance  A reference to the OpenThread instance.
557      *
558      */
559     explicit Server(Instance &aInstance);
560 
561     /**
562      * This method sets the SRP service events handler.
563      *
564      * @param[in]  aServiceHandler         A service events handler.
565      * @param[in]  aServiceHandlerContext  A pointer to arbitrary context information.
566      *
567      * @note  The handler SHOULD call HandleServiceUpdateResult to report the result of its processing.
568      *        Otherwise, a SRP update will be considered failed.
569      *
570      * @sa  HandleServiceUpdateResult
571      *
572      */
573     void SetServiceHandler(otSrpServerServiceUpdateHandler aServiceHandler, void *aServiceHandlerContext);
574 
575     /**
576      * This method returns the domain authorized to the SRP server.
577      *
578      * If the domain if not set by SetDomain, "default.service.arpa." will be returned.
579      * A trailing dot is always appended even if the domain is set without it.
580      *
581      * @returns A pointer to the dot-joined domain string.
582      *
583      */
GetDomain(void) const584     const char *GetDomain(void) const { return mDomain.AsCString(); }
585 
586     /**
587      * This method sets the domain on the SRP server.
588      *
589      * A trailing dot will be appended to @p aDomain if it is not already there.
590      * This method should only be called before the SRP server is enabled.
591      *
592      * @param[in]  aDomain  The domain to be set. MUST NOT be nullptr.
593      *
594      * @retval  kErrorNone          Successfully set the domain to @p aDomain.
595      * @retval  kErrorInvalidState  The SRP server is already enabled and the Domain cannot be changed.
596      * @retval  kErrorInvalidArgs   The argument @p aDomain is not a valid DNS domain name.
597      * @retval  kErrorNoBufs        There is no memory to store content of @p aDomain.
598      *
599      */
600     Error SetDomain(const char *aDomain);
601 
602     /**
603      * This method tells whether the SRP server is currently running.
604      *
605      * @returns  A boolean that indicates whether the server is running.
606      *
607      */
IsRunning(void) const608     bool IsRunning(void) const { return (mState == kStateRunning); }
609 
610     /**
611      * This method tells the state of the SRP server.
612      *
613      * @returns  An enum that represents the state of the server.
614      *
615      */
GetState(void) const616     State GetState(void) const { return mState; }
617 
618     /**
619      * This method enables/disables the SRP server.
620      *
621      * @param[in]  aEnabled  A boolean to enable/disable the SRP server.
622      *
623      */
624     void SetEnabled(bool aEnabled);
625 
626     /**
627      * This method returns the LEASE and KEY-LEASE configurations.
628      *
629      * @param[out]  aLeaseConfig  A reference to the `LeaseConfig` instance.
630      *
631      */
GetLeaseConfig(LeaseConfig & aLeaseConfig) const632     void GetLeaseConfig(LeaseConfig &aLeaseConfig) const { aLeaseConfig = mLeaseConfig; }
633 
634     /**
635      * This method sets the LEASE and KEY-LEASE configurations.
636      *
637      * When a LEASE time is requested from a client, the granted value will be
638      * limited in range [aMinLease, aMaxLease]; and a KEY-LEASE will be granted
639      * in range [aMinKeyLease, aMaxKeyLease].
640      *
641      * @param[in]  aLeaseConfig  A reference to the `LeaseConfig` instance.
642      *
643      * @retval  kErrorNone         Successfully set the LEASE and KEY-LEASE ranges.
644      * @retval  kErrorInvalidArgs  The LEASE or KEY-LEASE range is not valid.
645      *
646      */
647     Error SetLeaseConfig(const LeaseConfig &aLeaseConfig);
648 
649     /**
650      * This method returns the next registered SRP host.
651      *
652      * @param[in]  aHost  The current SRP host; use nullptr to get the first SRP host.
653      *
654      * @returns  A pointer to the next SRP host or nullptr if no more SRP hosts can be found.
655      *
656      */
657     const Host *GetNextHost(const Host *aHost);
658 
659     /**
660      * This method receives the service update result from service handler set by
661      * SetServiceHandler.
662      *
663      * @param[in]  aId     The ID of the service update transaction.
664      * @param[in]  aError  The service update result.
665      *
666      */
667     void HandleServiceUpdateResult(ServiceUpdateId aId, Error aError);
668 
669 private:
670     static constexpr uint16_t kUdpPayloadSize = Ip6::Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header);
671 
672     static constexpr uint32_t kDefaultMinLease             = 60u * 30;        // 30 min (in seconds).
673     static constexpr uint32_t kDefaultMaxLease             = 3600u * 2;       // 2 hours (in seconds).
674     static constexpr uint32_t kDefaultMinKeyLease          = 3600u * 24;      // 1 day (in seconds).
675     static constexpr uint32_t kDefaultMaxKeyLease          = 3600u * 24 * 14; // 14 days (in seconds).
676     static constexpr uint32_t kDefaultEventsHandlerTimeout = OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT;
677 
678     // This class includes metadata for processing a SRP update (register, deregister)
679     // and sending DNS response to the client.
680     class UpdateMetadata : public InstanceLocator, public LinkedListEntry<UpdateMetadata>
681     {
682         friend class LinkedListEntry<UpdateMetadata>;
683 
684     public:
685         static UpdateMetadata *  New(Instance &               aInstance,
686                                      const Dns::UpdateHeader &aHeader,
687                                      Host *                   aHost,
688                                      const Ip6::MessageInfo & aMessageInfo);
689         void                     Free(void);
GetExpireTime(void) const690         TimeMilli                GetExpireTime(void) const { return mExpireTime; }
GetDnsHeader(void) const691         const Dns::UpdateHeader &GetDnsHeader(void) const { return mDnsHeader; }
GetId(void) const692         ServiceUpdateId          GetId(void) const { return mId; }
GetHost(void)693         Host &                   GetHost(void) { return *mHost; }
GetMessageInfo(void) const694         const Ip6::MessageInfo & GetMessageInfo(void) const { return mMessageInfo; }
Matches(ServiceUpdateId aId) const695         bool                     Matches(ServiceUpdateId aId) const { return mId == aId; }
696 
697     private:
698         UpdateMetadata(Instance &               aInstance,
699                        const Dns::UpdateHeader &aHeader,
700                        Host *                   aHost,
701                        const Ip6::MessageInfo & aMessageInfo);
702 
703         TimeMilli         mExpireTime;
704         Dns::UpdateHeader mDnsHeader;
705         ServiceUpdateId   mId;          // The ID of this service update transaction.
706         Host *            mHost;        // The host will be updated. The UpdateMetadata has no ownership of this host.
707         Ip6::MessageInfo  mMessageInfo; // The message info of the DNS update request.
708         UpdateMetadata *  mNext;
709     };
710 
711     void Start(void);
712     void Stop(void);
713     void SelectPort(void);
714     void HandleNetDataPublisherEvent(NetworkData::Publisher::Event aEvent);
715 
AllocateId(void)716     ServiceUpdateId AllocateId(void) { return mServiceUpdateId++; }
717 
718     void  CommitSrpUpdate(Error                    aError,
719                           const Dns::UpdateHeader &aDnsHeader,
720                           Host &                   aHost,
721                           const Ip6::MessageInfo & aMessageInfo);
722     void  HandleDnsUpdate(Message &                aMessage,
723                           const Ip6::MessageInfo & aMessageInfo,
724                           const Dns::UpdateHeader &aDnsHeader,
725                           uint16_t                 aOffset);
726     Error ProcessUpdateSection(Host &                   aHost,
727                                const Message &          aMessage,
728                                const Dns::UpdateHeader &aDnsHeader,
729                                const Dns::Zone &        aZone,
730                                uint16_t &               aOffset) const;
731     Error ProcessAdditionalSection(Host *                   aHost,
732                                    const Message &          aMessage,
733                                    const Dns::UpdateHeader &aDnsHeader,
734                                    uint16_t &               aOffset) const;
735     Error VerifySignature(const Dns::Ecdsa256KeyRecord &aKey,
736                           const Message &               aMessage,
737                           Dns::UpdateHeader             aDnsHeader,
738                           uint16_t                      aSigOffset,
739                           uint16_t                      aSigRdataOffset,
740                           uint16_t                      aSigRdataLength,
741                           const char *                  aSignerName) const;
742     Error ProcessZoneSection(const Message &          aMessage,
743                              const Dns::UpdateHeader &aDnsHeader,
744                              uint16_t &               aOffset,
745                              Dns::Zone &              aZone) const;
746     Error ProcessHostDescriptionInstruction(Host &                   aHost,
747                                             const Message &          aMessage,
748                                             const Dns::UpdateHeader &aDnsHeader,
749                                             const Dns::Zone &        aZone,
750                                             uint16_t                 aOffset) const;
751     Error ProcessServiceDiscoveryInstructions(Host &                   aHost,
752                                               const Message &          aMessage,
753                                               const Dns::UpdateHeader &aDnsHeader,
754                                               const Dns::Zone &        aZone,
755                                               uint16_t                 aOffset) const;
756     Error ProcessServiceDescriptionInstructions(Host &                   aHost,
757                                                 const Message &          aMessage,
758                                                 const Dns::UpdateHeader &aDnsHeader,
759                                                 const Dns::Zone &        aZone,
760                                                 uint16_t &               aOffset) const;
761 
762     static bool IsValidDeleteAllRecord(const Dns::ResourceRecord &aRecord);
763 
764     void        HandleUpdate(const Dns::UpdateHeader &aDnsHeader, Host &aHost, const Ip6::MessageInfo &aMessageInfo);
765     void        AddHost(Host &aHost);
766     void        RemoveHost(Host *aHost, bool aRetainName, bool aNotifyServiceHandler);
767     bool        HasNameConflictsWith(Host &aHost) const;
768     void        SendResponse(const Dns::UpdateHeader &   aHeader,
769                              Dns::UpdateHeader::Response aResponseCode,
770                              const Ip6::MessageInfo &    aMessageInfo);
771     void        SendResponse(const Dns::UpdateHeader &aHeader,
772                              uint32_t                 aLease,
773                              uint32_t                 aKeyLease,
774                              const Ip6::MessageInfo & aMessageInfo);
775     static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
776     void        HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
777     static void HandleLeaseTimer(Timer &aTimer);
778     void        HandleLeaseTimer(void);
779     static void HandleOutstandingUpdatesTimer(Timer &aTimer);
780     void        HandleOutstandingUpdatesTimer(void);
781 
782     void                  HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError);
783     const UpdateMetadata *FindOutstandingUpdate(const Ip6::MessageInfo &aMessageInfo, uint16_t aDnsMessageId);
784 
785     Ip6::Udp::Socket                mSocket;
786     otSrpServerServiceUpdateHandler mServiceUpdateHandler;
787     void *                          mServiceUpdateHandlerContext;
788 
789     HeapString mDomain;
790 
791     LeaseConfig mLeaseConfig;
792 
793     LinkedList<Host> mHosts;
794     TimerMilli       mLeaseTimer;
795 
796     TimerMilli                 mOutstandingUpdatesTimer;
797     LinkedList<UpdateMetadata> mOutstandingUpdates;
798 
799     ServiceUpdateId mServiceUpdateId;
800     uint16_t        mPort;
801     State           mState;
802     bool            mHasRegisteredAnyService : 1;
803 };
804 
805 } // namespace Srp
806 } // namespace ot
807 
808 #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
809 #endif // NET_SRP_SERVER_HPP_
810