1 /*
2  *  Copyright (c) 2016, 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 non-volatile storage of settings.
32  */
33 
34 #ifndef SETTINGS_HPP_
35 #define SETTINGS_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/platform/settings.h>
40 
41 #include "common/clearable.hpp"
42 #include "common/encoding.hpp"
43 #include "common/equatable.hpp"
44 #include "common/locator.hpp"
45 #include "common/non_copyable.hpp"
46 #include "common/settings_driver.hpp"
47 #include "mac/mac_types.hpp"
48 #include "net/ip6_address.hpp"
49 #include "utils/flash.hpp"
50 #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
51 #include "utils/slaac_address.hpp"
52 #endif
53 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
54 #include "crypto/ecdsa.hpp"
55 #endif
56 
57 namespace ot {
58 
59 namespace MeshCoP {
60 class Dataset;
61 }
62 
63 class Settings;
64 
65 /**
66  * This class defines the base class used by `Settings` and `Settings::ChildInfoIterator`.
67  *
68  * This class provides structure definitions for different settings keys.
69  *
70  */
71 class SettingsBase : public InstanceLocator
72 {
73 protected:
74     enum Action : uint8_t
75     {
76         kActionRead,
77         kActionSave,
78         kActionResave,
79         kActionDelete,
80 #if OPENTHREAD_FTD
81         kActionAdd,
82         kActionRemove,
83         kActionDeleteAll,
84 #endif
85     };
86 
87 public:
88     /**
89      * Rules for updating existing value structures.
90      *
91      * 1. Modifying existing key value fields in settings MUST only be
92      *    done by appending new fields.  Existing fields MUST NOT be
93      *    deleted or modified in any way.
94      *
95      * 2. To support backward compatibility (rolling back to an older
96      *    software version), code reading and processing key values MUST
97      *    process key values that have longer length.  Additionally, newer
98      *    versions MUST update/maintain values in existing key value
99      *    fields.
100      *
101      * 3. To support forward compatibility (rolling forward to a newer
102      *    software version), code reading and processing key values MUST
103      *    process key values that have shorter length.
104      *
105      * 4. New Key IDs may be defined in the future with the understanding
106      *    that such key values are not backward compatible.
107      *
108      */
109 
110     /**
111      * This enumeration defines the keys of settings.
112      *
113      */
114     enum Key : uint16_t
115     {
116         kKeyActiveDataset     = OT_SETTINGS_KEY_ACTIVE_DATASET,
117         kKeyPendingDataset    = OT_SETTINGS_KEY_PENDING_DATASET,
118         kKeyNetworkInfo       = OT_SETTINGS_KEY_NETWORK_INFO,
119         kKeyParentInfo        = OT_SETTINGS_KEY_PARENT_INFO,
120         kKeyChildInfo         = OT_SETTINGS_KEY_CHILD_INFO,
121         kKeyReserved          = OT_SETTINGS_KEY_RESERVED,
122         kKeySlaacIidSecretKey = OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY,
123         kKeyDadInfo           = OT_SETTINGS_KEY_DAD_INFO,
124         kKeyOmrPrefix         = OT_SETTINGS_KEY_OMR_PREFIX,
125         kKeyOnLinkPrefix      = OT_SETTINGS_KEY_ON_LINK_PREFIX,
126         kKeySrpEcdsaKey       = OT_SETTINGS_KEY_SRP_ECDSA_KEY,
127         kKeySrpClientInfo     = OT_SETTINGS_KEY_SRP_CLIENT_INFO,
128         kKeySrpServerInfo     = OT_SETTINGS_KEY_SRP_SERVER_INFO,
129     };
130 
131     static constexpr Key kLastKey = kKeySrpServerInfo; ///< The last (numerically) enumerator value in `Key`.
132 
133     /**
134      * This structure represents the device's own network information for settings storage.
135      *
136      */
137     OT_TOOL_PACKED_BEGIN
138     class NetworkInfo : private Clearable<NetworkInfo>
139     {
140         friend class Settings;
141 
142     public:
143         static constexpr Key kKey = kKeyNetworkInfo; ///< The associated key.
144 
145         /**
146          * This method initializes the `NetworkInfo` object.
147          *
148          */
Init(void)149         void Init(void)
150         {
151             Clear();
152             SetVersion(OT_THREAD_VERSION_1_1);
153         }
154 
155         /**
156          * This method returns the Thread role.
157          *
158          * @returns The Thread role.
159          *
160          */
GetRole(void) const161         uint8_t GetRole(void) const { return mRole; }
162 
163         /**
164          * This method sets the Thread role.
165          *
166          * @param[in] aRole  The Thread Role.
167          *
168          */
SetRole(uint8_t aRole)169         void SetRole(uint8_t aRole) { mRole = aRole; }
170 
171         /**
172          * This method returns the Thread device mode.
173          *
174          * @returns the Thread device mode.
175          *
176          */
GetDeviceMode(void) const177         uint8_t GetDeviceMode(void) const { return mDeviceMode; }
178 
179         /**
180          * This method sets the Thread device mode.
181          *
182          * @param[in] aDeviceMode  The Thread device mode.
183          *
184          */
SetDeviceMode(uint8_t aDeviceMode)185         void SetDeviceMode(uint8_t aDeviceMode) { mDeviceMode = aDeviceMode; }
186 
187         /**
188          * This method returns the RLOC16.
189          *
190          * @returns The RLOC16.
191          *
192          */
GetRloc16(void) const193         uint16_t GetRloc16(void) const { return Encoding::LittleEndian::HostSwap16(mRloc16); }
194 
195         /**
196          * This method sets the RLOC16.
197          *
198          * @param[in] aRloc16  The RLOC16.
199          *
200          */
SetRloc16(uint16_t aRloc16)201         void SetRloc16(uint16_t aRloc16) { mRloc16 = Encoding::LittleEndian::HostSwap16(aRloc16); }
202 
203         /**
204          * This method returns the key sequence.
205          *
206          * @returns The key sequence.
207          *
208          */
GetKeySequence(void) const209         uint32_t GetKeySequence(void) const { return Encoding::LittleEndian::HostSwap32(mKeySequence); }
210 
211         /**
212          * This method sets the key sequence.
213          *
214          * @param[in] aKeySequence  The key sequence.
215          *
216          */
SetKeySequence(uint32_t aKeySequence)217         void SetKeySequence(uint32_t aKeySequence) { mKeySequence = Encoding::LittleEndian::HostSwap32(aKeySequence); }
218 
219         /**
220          * This method returns the MLE frame counter.
221          *
222          * @returns The MLE frame counter.
223          *
224          */
GetMleFrameCounter(void) const225         uint32_t GetMleFrameCounter(void) const { return Encoding::LittleEndian::HostSwap32(mMleFrameCounter); }
226 
227         /**
228          * This method sets the MLE frame counter.
229          *
230          * @param[in] aMleFrameCounter  The MLE frame counter.
231          *
232          */
SetMleFrameCounter(uint32_t aMleFrameCounter)233         void SetMleFrameCounter(uint32_t aMleFrameCounter)
234         {
235             mMleFrameCounter = Encoding::LittleEndian::HostSwap32(aMleFrameCounter);
236         }
237 
238         /**
239          * This method returns the MAC frame counter.
240          *
241          * @returns The MAC frame counter.
242          *
243          */
GetMacFrameCounter(void) const244         uint32_t GetMacFrameCounter(void) const { return Encoding::LittleEndian::HostSwap32(mMacFrameCounter); }
245 
246         /**
247          * This method sets the MAC frame counter.
248          *
249          * @param[in] aMacFrameCounter  The MAC frame counter.
250          *
251          */
SetMacFrameCounter(uint32_t aMacFrameCounter)252         void SetMacFrameCounter(uint32_t aMacFrameCounter)
253         {
254             mMacFrameCounter = Encoding::LittleEndian::HostSwap32(aMacFrameCounter);
255         }
256 
257         /**
258          * This method returns the previous partition ID.
259          *
260          * @returns The previous partition ID.
261          *
262          */
GetPreviousPartitionId(void) const263         uint32_t GetPreviousPartitionId(void) const { return Encoding::LittleEndian::HostSwap32(mPreviousPartitionId); }
264 
265         /**
266          * This method sets the previous partition id.
267          *
268          * @param[in] aPreviousPartitionId  The previous partition ID.
269          *
270          */
SetPreviousPartitionId(uint32_t aPreviousPartitionId)271         void SetPreviousPartitionId(uint32_t aPreviousPartitionId)
272         {
273             mPreviousPartitionId = Encoding::LittleEndian::HostSwap32(aPreviousPartitionId);
274         }
275 
276         /**
277          * This method returns the extended address.
278          *
279          * @returns The extended address.
280          *
281          */
GetExtAddress(void) const282         const Mac::ExtAddress &GetExtAddress(void) const { return mExtAddress; }
283 
284         /**
285          * This method sets the extended address.
286          *
287          * @param[in] aExtAddress  The extended address.
288          *
289          */
SetExtAddress(const Mac::ExtAddress & aExtAddress)290         void SetExtAddress(const Mac::ExtAddress &aExtAddress) { mExtAddress = aExtAddress; }
291 
292         /**
293          * This method returns the Mesh Local Interface Identifier.
294          *
295          * @returns The Mesh Local Interface Identifier.
296          *
297          */
GetMeshLocalIid(void) const298         const Ip6::InterfaceIdentifier &GetMeshLocalIid(void) const { return mMlIid; }
299 
300         /**
301          * This method sets the Mesh Local Interface Identifier.
302          *
303          * @param[in] aMeshLocalIid  The Mesh Local Interface Identifier.
304          *
305          */
SetMeshLocalIid(const Ip6::InterfaceIdentifier & aMeshLocalIid)306         void SetMeshLocalIid(const Ip6::InterfaceIdentifier &aMeshLocalIid) { mMlIid = aMeshLocalIid; }
307 
308         /**
309          * This method returns the Thread version.
310          *
311          * @returns The Thread version.
312          *
313          */
GetVersion(void) const314         uint16_t GetVersion(void) const { return Encoding::LittleEndian::HostSwap16(mVersion); }
315 
316         /**
317          * This method sets the Thread version.
318          *
319          * @param[in] aVersion  The Thread version.
320          *
321          */
SetVersion(uint16_t aVersion)322         void SetVersion(uint16_t aVersion) { mVersion = Encoding::LittleEndian::HostSwap16(aVersion); }
323 
324     private:
325         void Log(Action aAction) const;
326 
327         uint8_t                  mRole;                ///< Current Thread role.
328         uint8_t                  mDeviceMode;          ///< Device mode setting.
329         uint16_t                 mRloc16;              ///< RLOC16
330         uint32_t                 mKeySequence;         ///< Key Sequence
331         uint32_t                 mMleFrameCounter;     ///< MLE Frame Counter
332         uint32_t                 mMacFrameCounter;     ///< MAC Frame Counter
333         uint32_t                 mPreviousPartitionId; ///< PartitionId
334         Mac::ExtAddress          mExtAddress;          ///< Extended Address
335         Ip6::InterfaceIdentifier mMlIid;               ///< IID from ML-EID
336         uint16_t                 mVersion;             ///< Version
337     } OT_TOOL_PACKED_END;
338 
339     /**
340      * This structure represents the parent information for settings storage.
341      *
342      */
343     OT_TOOL_PACKED_BEGIN
344     class ParentInfo : private Clearable<ParentInfo>
345     {
346         friend class Settings;
347 
348     public:
349         static constexpr Key kKey = kKeyParentInfo; ///< The associated key.
350 
351         /**
352          * This method initializes the `ParentInfo` object.
353          *
354          */
Init(void)355         void Init(void)
356         {
357             Clear();
358             SetVersion(OT_THREAD_VERSION_1_1);
359         }
360 
361         /**
362          * This method returns the extended address.
363          *
364          * @returns The extended address.
365          *
366          */
GetExtAddress(void) const367         const Mac::ExtAddress &GetExtAddress(void) const { return mExtAddress; }
368 
369         /**
370          * This method sets the extended address.
371          *
372          * @param[in] aExtAddress  The extended address.
373          *
374          */
SetExtAddress(const Mac::ExtAddress & aExtAddress)375         void SetExtAddress(const Mac::ExtAddress &aExtAddress) { mExtAddress = aExtAddress; }
376 
377         /**
378          * This method returns the Thread version.
379          *
380          * @returns The Thread version.
381          *
382          */
GetVersion(void) const383         uint16_t GetVersion(void) const { return Encoding::LittleEndian::HostSwap16(mVersion); }
384 
385         /**
386          * This method sets the Thread version.
387          *
388          * @param[in] aVersion  The Thread version.
389          *
390          */
SetVersion(uint16_t aVersion)391         void SetVersion(uint16_t aVersion) { mVersion = Encoding::LittleEndian::HostSwap16(aVersion); }
392 
393     private:
394         void Log(Action aAction) const;
395 
396         Mac::ExtAddress mExtAddress; ///< Extended Address
397         uint16_t        mVersion;    ///< Version
398     } OT_TOOL_PACKED_END;
399 
400 #if OPENTHREAD_FTD
401     /**
402      * This structure represents the child information for settings storage.
403      *
404      */
405     OT_TOOL_PACKED_BEGIN
406     class ChildInfo
407     {
408         friend class Settings;
409 
410     public:
411         static constexpr Key kKey = kKeyChildInfo; ///< The associated key.
412 
413         /**
414          * This method clears the struct object (setting all the fields to zero).
415          *
416          */
Init(void)417         void Init(void)
418         {
419             memset(this, 0, sizeof(*this));
420             SetVersion(OT_THREAD_VERSION_1_1);
421         }
422 
423         /**
424          * This method returns the extended address.
425          *
426          * @returns The extended address.
427          *
428          */
GetExtAddress(void) const429         const Mac::ExtAddress &GetExtAddress(void) const { return mExtAddress; }
430 
431         /**
432          * This method sets the extended address.
433          *
434          * @param[in] aExtAddress  The extended address.
435          *
436          */
SetExtAddress(const Mac::ExtAddress & aExtAddress)437         void SetExtAddress(const Mac::ExtAddress &aExtAddress) { mExtAddress = aExtAddress; }
438 
439         /**
440          * This method returns the child timeout.
441          *
442          * @returns The child timeout.
443          *
444          */
GetTimeout(void) const445         uint32_t GetTimeout(void) const { return Encoding::LittleEndian::HostSwap32(mTimeout); }
446 
447         /**
448          * This method sets the child timeout.
449          *
450          * @param[in] aTimeout  The child timeout.
451          *
452          */
SetTimeout(uint32_t aTimeout)453         void SetTimeout(uint32_t aTimeout) { mTimeout = Encoding::LittleEndian::HostSwap32(aTimeout); }
454 
455         /**
456          * This method returns the RLOC16.
457          *
458          * @returns The RLOC16.
459          *
460          */
GetRloc16(void) const461         uint16_t GetRloc16(void) const { return Encoding::LittleEndian::HostSwap16(mRloc16); }
462 
463         /**
464          * This method sets the RLOC16.
465          *
466          * @param[in] aRloc16  The RLOC16.
467          *
468          */
SetRloc16(uint16_t aRloc16)469         void SetRloc16(uint16_t aRloc16) { mRloc16 = Encoding::LittleEndian::HostSwap16(aRloc16); }
470 
471         /**
472          * This method returns the Thread device mode.
473          *
474          * @returns The Thread device mode.
475          *
476          */
GetMode(void) const477         uint8_t GetMode(void) const { return mMode; }
478 
479         /**
480          * This method sets the Thread device mode.
481          *
482          * @param[in] aRloc16  The Thread device mode.
483          *
484          */
SetMode(uint8_t aMode)485         void SetMode(uint8_t aMode) { mMode = aMode; }
486 
487         /**
488          * This method returns the Thread version.
489          *
490          * @returns The Thread version.
491          *
492          */
GetVersion(void) const493         uint16_t GetVersion(void) const { return Encoding::LittleEndian::HostSwap16(mVersion); }
494 
495         /**
496          * This method sets the Thread version.
497          *
498          * @param[in] aVersion  The Thread version.
499          *
500          */
SetVersion(uint16_t aVersion)501         void SetVersion(uint16_t aVersion) { mVersion = Encoding::LittleEndian::HostSwap16(aVersion); }
502 
503     private:
504         void Log(Action aAction) const;
505 
506         Mac::ExtAddress mExtAddress; ///< Extended Address
507         uint32_t        mTimeout;    ///< Timeout
508         uint16_t        mRloc16;     ///< RLOC16
509         uint8_t         mMode;       ///< The MLE device mode
510         uint16_t        mVersion;    ///< Version
511     } OT_TOOL_PACKED_END;
512 #endif // OPENTHREAD_FTD
513 
514 #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
515     /**
516      * This class defines constants and types for SLAAC IID Secret key settings.
517      *
518      */
519     class SlaacIidSecretKey
520     {
521     public:
522         static constexpr Key kKey = kKeySlaacIidSecretKey; ///< The associated key.
523 
524         typedef Utils::Slaac::IidSecretKey ValueType; ///< The associated value type.
525 
526     private:
527         SlaacIidSecretKey(void) = default;
528     };
529 #endif
530 
531 #if OPENTHREAD_CONFIG_DUA_ENABLE
532     /**
533      * This structure represents the duplicate address detection information for settings storage.
534      *
535      */
536     OT_TOOL_PACKED_BEGIN
537     class DadInfo : private Clearable<DadInfo>
538     {
539         friend class Settings;
540 
541     public:
542         static constexpr Key kKey = kKeyDadInfo; ///< The associated key.
543 
544         /**
545          * This method initializes the `DadInfo` object.
546          *
547          */
Init(void)548         void Init(void) { Clear(); }
549 
550         /**
551          * This method returns the Dad Counter.
552          *
553          * @returns The Dad Counter value.
554          *
555          */
GetDadCounter(void) const556         uint8_t GetDadCounter(void) const { return mDadCounter; }
557 
558         /**
559          * This method sets the Dad Counter.
560          *
561          * @param[in] aDadCounter The Dad Counter value.
562          *
563          */
SetDadCounter(uint8_t aDadCounter)564         void SetDadCounter(uint8_t aDadCounter) { mDadCounter = aDadCounter; }
565 
566     private:
567         void Log(Action aAction) const;
568 
569         uint8_t mDadCounter; ///< Dad Counter used to resolve address conflict in Thread 1.2 DUA feature.
570     } OT_TOOL_PACKED_END;
571 #endif // OPENTHREAD_CONFIG_DUA_ENABLE
572 
573 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
574     /**
575      * This class defines constants and types for OMR prefix settings.
576      *
577      */
578     class OmrPrefix
579     {
580     public:
581         static constexpr Key kKey = kKeyOmrPrefix; ///< The associated key.
582 
583         typedef Ip6::Prefix ValueType; ///< The associated value type.
584 
585     private:
586         OmrPrefix(void) = default;
587     };
588 
589     /**
590      * This class defines constants and types for on-link prefix settings.
591      *
592      */
593     class OnLinkPrefix
594     {
595     public:
596         static constexpr Key kKey = kKeyOnLinkPrefix; ///< The associated key.
597 
598         typedef Ip6::Prefix ValueType; ///< The associated value type.
599 
600     private:
601         OnLinkPrefix(void) = default;
602     };
603 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
604 
605 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
606     /**
607      * This class defines constants and types for SRP ECDSA key settings.
608      *
609      */
610     class SrpEcdsaKey
611     {
612     public:
613         static constexpr Key kKey = kKeySrpEcdsaKey; ///< The associated key.
614 
615         typedef Crypto::Ecdsa::P256::KeyPair ValueType; ///< The associated value type.
616 
617     private:
618         SrpEcdsaKey(void) = default;
619     };
620 
621 #if OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
622     /**
623      * This structure represents the SRP client info (selected server address).
624      *
625      */
626     OT_TOOL_PACKED_BEGIN
627     class SrpClientInfo : private Clearable<SrpClientInfo>
628     {
629         friend class Settings;
630 
631     public:
632         static constexpr Key kKey = kKeySrpClientInfo; ///< The associated key.
633 
634         /**
635          * This method initializes the `SrpClientInfo` object.
636          *
637          */
Init(void)638         void Init(void) { Clear(); }
639 
640         /**
641          * This method returns the server IPv6 address.
642          *
643          * @returns The server IPv6 address.
644          *
645          */
GetServerAddress(void) const646         const Ip6::Address &GetServerAddress(void) const { return mServerAddress; }
647 
648         /**
649          * This method sets the server IPv6 address.
650          *
651          * @param[in] aAddress  The server IPv6 address.
652          *
653          */
SetServerAddress(const Ip6::Address & aAddress)654         void SetServerAddress(const Ip6::Address &aAddress) { mServerAddress = aAddress; }
655 
656         /**
657          * This method returns the server port number.
658          *
659          * @returns The server port number.
660          *
661          */
GetServerPort(void) const662         uint16_t GetServerPort(void) const { return Encoding::LittleEndian::HostSwap16(mServerPort); }
663 
664         /**
665          * This method sets the server port number.
666          *
667          * @param[in] aPort  The server port number.
668          *
669          */
SetServerPort(uint16_t aPort)670         void SetServerPort(uint16_t aPort) { mServerPort = Encoding::LittleEndian::HostSwap16(aPort); }
671 
672     private:
673         void Log(Action aAction) const;
674 
675         Ip6::Address mServerAddress;
676         uint16_t     mServerPort; // (in little-endian encoding)
677     } OT_TOOL_PACKED_END;
678 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
679 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
680 
681 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
682     /**
683      * This structure represents the SRP server info.
684      *
685      */
686     OT_TOOL_PACKED_BEGIN
687     class SrpServerInfo : private Clearable<SrpServerInfo>
688     {
689         friend class Settings;
690 
691     public:
692         static constexpr Key kKey = kKeySrpServerInfo; ///< The associated key.
693 
694         /**
695          * This method initializes the `SrpServerInfo` object.
696          *
697          */
Init(void)698         void Init(void) { Clear(); }
699 
700         /**
701          * This method returns the server port number.
702          *
703          * @returns The server port number.
704          *
705          */
GetPort(void) const706         uint16_t GetPort(void) const { return Encoding::LittleEndian::HostSwap16(mPort); }
707 
708         /**
709          * This method sets the server port number.
710          *
711          * @param[in] aPort  The server port number.
712          *
713          */
SetPort(uint16_t aPort)714         void SetPort(uint16_t aPort) { mPort = Encoding::LittleEndian::HostSwap16(aPort); }
715 
716     private:
717         void Log(Action aAction) const;
718 
719         uint16_t mPort; // (in little-endian encoding)
720     } OT_TOOL_PACKED_END;
721 #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
722 
723 protected:
SettingsBase(Instance & aInstance)724     explicit SettingsBase(Instance &aInstance)
725         : InstanceLocator(aInstance)
726     {
727     }
728 
729 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
730     static void LogPrefix(Action aAction, Key aKey, const Ip6::Prefix &aPrefix);
731 #endif
732 
733 #if OPENTHREAD_CONFIG_LOG_UTIL && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN)
734     static const char *KeyToString(Key aKey);
735 #endif
736 #if OPENTHREAD_CONFIG_LOG_UTIL && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO)
737     static const char *ActionToString(Action aAction);
738 #endif
739 };
740 
741 /**
742  * This class defines methods related to non-volatile storage of settings.
743  *
744  */
745 class Settings : public SettingsBase, private NonCopyable
746 {
747     class ChildInfoIteratorBuilder;
748 
749 public:
750     /**
751      * This constructor initializes a `Settings` object.
752      *
753      * @param[in]  aInstance     A reference to the OpenThread instance.
754      *
755      */
Settings(Instance & aInstance)756     explicit Settings(Instance &aInstance)
757         : SettingsBase(aInstance)
758     {
759     }
760 
761     /**
762      * This method initializes the platform settings (non-volatile) module.
763      *
764      * This should be called before any other method from this class.
765      *
766      */
767     void Init(void);
768 
769     /**
770      * This method de-initializes the platform settings (non-volatile) module.
771      *
772      * This method should be called when OpenThread instance is no longer in use.
773      *
774      */
775     void Deinit(void);
776 
777     /**
778      * This method removes all settings from the non-volatile store.
779      *
780      */
781     void Wipe(void);
782 
783     /**
784      * This method saves the Operational Dataset (active or pending).
785      *
786      * @param[in]   aIsActive   Indicates whether Dataset is active or pending.
787      * @param[in]   aDataset    A reference to a `Dataset` object to be saved.
788      *
789      * @retval kErrorNone             Successfully saved the Dataset.
790      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
791      *
792      */
793     Error SaveOperationalDataset(bool aIsActive, const MeshCoP::Dataset &aDataset);
794 
795     /**
796      * This method reads the Operational Dataset (active or pending).
797      *
798      * @param[in]   aIsActive             Indicates whether Dataset is active or pending.
799      * @param[out]  aDataset              A reference to a `Dataset` object to output the read content.
800      *
801      * @retval kErrorNone             Successfully read the Dataset.
802      * @retval kErrorNotFound         No corresponding value in the setting store.
803      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
804      *
805      */
806     Error ReadOperationalDataset(bool aIsActive, MeshCoP::Dataset &aDataset) const;
807 
808     /**
809      * This method deletes the Operational Dataset (active/pending) from settings.
810      *
811      * @param[in]   aIsActive            Indicates whether Dataset is active or pending.
812      *
813      * @retval kErrorNone            Successfully deleted the Dataset.
814      * @retval kErrorNotImplemented  The platform does not implement settings functionality.
815      *
816      */
817     Error DeleteOperationalDataset(bool aIsActive);
818 
819     /**
820      * This template method reads a specified settings entry.
821      *
822      * The template type `EntryType` specifies the entry's value data structure. It must provide the following:
823      *
824      *  - It must provide a constant `EntryType::kKey` to specify the associated entry settings key.
825      *  - It must provide method `Init()` to initialize the `aEntry` object.
826      *
827      * This version of `Read<EntryType>` is intended for use with entries that define a data structure which represents
828      * the entry's value, e.g., `NetworkInfo`, `ParentInfo`, `DadInfo`, etc.
829      *
830      * @tparam EntryType              The settings entry type.
831      *
832      * @param[out] aEntry             A reference to a entry data structure to output the read content.
833      *
834      * @retval kErrorNone             Successfully read the entry.
835      * @retval kErrorNotFound         No corresponding value in the setting store.
836      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
837      *
838      */
Read(EntryType & aEntry) const839     template <typename EntryType> Error Read(EntryType &aEntry) const
840     {
841         aEntry.Init();
842 
843         return ReadEntry(EntryType::kKey, &aEntry, sizeof(EntryType));
844     }
845 
846     /**
847      * This template method reads a specified settings entry.
848      *
849      * The template type `EntryType` provides information about the entry's value type. It must provide the following:
850      *
851      *  - It must provide a constant `EntryType::kKey` to specify the associated entry settings key.
852      *  - It must provide a nested type `EntryType::ValueType` to specify the associated entry value type.
853      *
854      * This version of `Read<EntryType>` is intended for use with entries that have a simple entry value type (which can
855      * be represented by an existing type), e.g., `OmrPrefx` (using `Ip6::Prefix` as the value type).
856      *
857      * @tparam EntryType              The settings entry type.
858      *
859      * @param[out] aValue             A reference to a value type object to output the read content.
860      *
861      * @retval kErrorNone             Successfully read the value.
862      * @retval kErrorNotFound         No corresponding value in the setting store.
863      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
864      *
865      */
Read(typename EntryType::ValueType & aValue) const866     template <typename EntryType> Error Read(typename EntryType::ValueType &aValue) const
867     {
868         return ReadEntry(EntryType::kKey, &aValue, sizeof(typename EntryType::ValueType));
869     }
870 
871     /**
872      * This template method saves a specified settings entry.
873      *
874      * The template type `EntryType` specifies the entry's value data structure. It must provide the following:
875      *
876      *  - It must provide a constant `EntryType::kKey` to specify the associated entry settings key.
877      *
878      * This version of `Save<EntryType>` is intended for use with entries that define a data structure which represents
879      * the entry's value, e.g., `NetworkInfo`, `ParentInfo`, `DadInfo`, etc.
880      *
881      * @tparam EntryType              The settings entry type.
882      *
883      * @param[in] aEntry              The entry value to be saved.
884      *
885      * @retval kErrorNone             Successfully saved Network Info in settings.
886      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
887      *
888      */
Save(const EntryType & aEntry)889     template <typename EntryType> Error Save(const EntryType &aEntry)
890     {
891         EntryType prev;
892 
893         return SaveEntry(EntryType::kKey, &aEntry, &prev, sizeof(EntryType));
894     }
895 
896     /**
897      * This template method saves a specified settings entry.
898      *
899      * The template type `EntryType` provides information about the entry's value type. It must provide the following:
900      *
901      *  - It must provide a constant `EntryType::kKey` to specify the associated entry settings key.
902      *  - It must provide a nested type `EntryType::ValueType` to specify the associated entry value type.
903      *
904      * This version of `Save<EntryType>` is intended for use with entries that have a simple entry value type (which can
905      * be represented by an existing type), e.g., `OmrPrefx` (using `Ip6::Prefix` as the value type).
906      *
907      * @tparam EntryType              The settings entry type.
908      *
909      * @param[in] aEntry              The entry value to be saved.
910      *
911      * @retval kErrorNone             Successfully saved Network Info in settings.
912      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
913      *
914      */
Save(const typename EntryType::ValueType & aValue)915     template <typename EntryType> Error Save(const typename EntryType::ValueType &aValue)
916     {
917         typename EntryType::ValueType prev;
918 
919         return SaveEntry(EntryType::kKey, &aValue, &prev, sizeof(typename EntryType::ValueType));
920     }
921 
922     /**
923      * This template method deletes a specified setting entry.
924      *
925      * The template type `EntryType` provides information about the entry's key.
926      *
927      *  - It must provide a constant `EntryType::kKey` to specify the associated entry settings key.
928      *
929      * @tparam EntryType             The settings entry type.
930      *
931      * @retval kErrorNone            Successfully deleted the value.
932      * @retval kErrorNotImplemented  The platform does not implement settings functionality.
933      *
934      */
Delete(void)935     template <typename EntryType> Error Delete(void) { return DeleteEntry(EntryType::kKey); }
936 
937 #if OPENTHREAD_FTD
938     /**
939      * This method adds a Child Info entry to settings.
940      *
941      * @note Child Info is a list-based settings property and can contain multiple entries.
942      *
943      * @param[in]   aChildInfo            A reference to a `ChildInfo` structure to be saved/added.
944      *
945      * @retval kErrorNone             Successfully saved the Child Info in settings.
946      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
947      *
948      */
949     Error AddChildInfo(const ChildInfo &aChildInfo);
950 
951     /**
952      * This method deletes all Child Info entries from the settings.
953      *
954      * @note Child Info is a list-based settings property and can contain multiple entries.
955      *
956      * @retval kErrorNone            Successfully deleted the value.
957      * @retval kErrorNotImplemented  The platform does not implement settings functionality.
958      *
959      */
960     Error DeleteAllChildInfo(void);
961 
962     /**
963      * This method enables range-based `for` loop iteration over all child info entries in the `Settings`.
964      *
965      * This method should be used as follows:
966      *
967      *     for (const ChildInfo &childInfo : Get<Settings>().IterateChildInfo()) { ... }
968      *
969      *
970      * @returns A ChildInfoIteratorBuilder instance.
971      *
972      */
IterateChildInfo(void)973     ChildInfoIteratorBuilder IterateChildInfo(void) { return ChildInfoIteratorBuilder(GetInstance()); }
974 
975     /**
976      * This class defines an iterator to access all Child Info entries in the settings.
977      *
978      */
979     class ChildInfoIterator : public SettingsBase, public Unequatable<ChildInfoIterator>
980     {
981         friend class ChildInfoIteratorBuilder;
982 
983     public:
984         /**
985          * This constructor initializes a `ChildInfoInterator` object.
986          *
987          * @param[in]  aInstance  A reference to the OpenThread instance.
988          *
989          */
990         explicit ChildInfoIterator(Instance &aInstance);
991 
992         /**
993          * This method indicates whether there are no more Child Info entries in the list (iterator has reached end of
994          * the list), or the current entry is valid.
995          *
996          * @retval TRUE   There are no more entries in the list (reached end of the list).
997          * @retval FALSE  The current entry is valid.
998          *
999          */
IsDone(void) const1000         bool IsDone(void) const { return mIsDone; }
1001 
1002         /**
1003          * This method overloads operator `++` (pre-increment) to advance the iterator to move to the next Child Info
1004          * entry in the list (if any).
1005          *
1006          */
operator ++(void)1007         void operator++(void) { Advance(); }
1008 
1009         /**
1010          * This method overloads operator `++` (post-increment) to advance the iterator to move to the next Child Info
1011          * entry in the list (if any).
1012          *
1013          */
operator ++(int)1014         void operator++(int) { Advance(); }
1015 
1016         /**
1017          * This method gets the Child Info corresponding to the current iterator entry in the list.
1018          *
1019          * @note This method should be used only if `IsDone()` is returning FALSE indicating that the iterator is
1020          * pointing to a valid entry.
1021          *
1022          * @returns A reference to `ChildInfo` structure corresponding to current iterator entry.
1023          *
1024          */
GetChildInfo(void) const1025         const ChildInfo &GetChildInfo(void) const { return mChildInfo; }
1026 
1027         /**
1028          * This method deletes the current Child Info entry.
1029          *
1030          * @retval kErrorNone            The entry was deleted successfully.
1031          * @retval kErrorInvalidState    The entry is not valid (iterator has reached end of list).
1032          * @retval kErrorNotImplemented  The platform does not implement settings functionality.
1033          *
1034          */
1035         Error Delete(void);
1036 
1037         /**
1038          * This method overloads the `*` dereference operator and gets a reference to `ChildInfo` entry to which the
1039          * iterator is currently pointing.
1040          *
1041          * @note This method should be used only if `IsDone()` is returning FALSE indicating that the iterator is
1042          * pointing to a valid entry.
1043          *
1044          *
1045          * @returns A reference to the `ChildInfo` entry currently pointed by the iterator.
1046          *
1047          */
operator *(void) const1048         const ChildInfo &operator*(void)const { return mChildInfo; }
1049 
1050         /**
1051          * This method overloads operator `==` to evaluate whether or not two iterator instances are equal.
1052          *
1053          * @param[in]  aOther  The other iterator to compare with.
1054          *
1055          * @retval TRUE   If the two iterator objects are equal
1056          * @retval FALSE  If the two iterator objects are not equal.
1057          *
1058          */
operator ==(const ChildInfoIterator & aOther) const1059         bool operator==(const ChildInfoIterator &aOther) const
1060         {
1061             return (mIsDone && aOther.mIsDone) || (!mIsDone && !aOther.mIsDone && (mIndex == aOther.mIndex));
1062         }
1063 
1064     private:
1065         enum IteratorType : uint8_t
1066         {
1067             kEndIterator,
1068         };
1069 
ChildInfoIterator(Instance & aInstance,IteratorType)1070         ChildInfoIterator(Instance &aInstance, IteratorType)
1071             : SettingsBase(aInstance)
1072             , mIndex(0)
1073             , mIsDone(true)
1074         {
1075         }
1076 
1077         void Advance(void);
1078         void Read(void);
1079 
1080         ChildInfo mChildInfo;
1081         uint16_t  mIndex;
1082         bool      mIsDone;
1083     };
1084 #endif // OPENTHREAD_FTD
1085 
1086 private:
1087 #if OPENTHREAD_FTD
1088     class ChildInfoIteratorBuilder : public InstanceLocator
1089     {
1090     public:
ChildInfoIteratorBuilder(Instance & aInstance)1091         explicit ChildInfoIteratorBuilder(Instance &aInstance)
1092             : InstanceLocator(aInstance)
1093         {
1094         }
1095 
begin(void)1096         ChildInfoIterator begin(void) { return ChildInfoIterator(GetInstance()); }
end(void)1097         ChildInfoIterator end(void) { return ChildInfoIterator(GetInstance(), ChildInfoIterator::kEndIterator); }
1098     };
1099 #endif
1100 
1101     Error ReadEntry(Key aKey, void *aValue, uint16_t aMaxLength) const;
1102     Error SaveEntry(Key aKey, const void *aValue, void *aPrev, uint16_t aLength);
1103     Error DeleteEntry(Key aKey);
1104 
1105     static void Log(Action aAction, Error aError, Key aKey, const void *aValue = nullptr);
1106 
1107     static const uint16_t kCriticalKeys[];
1108 };
1109 
1110 } // namespace ot
1111 
1112 #endif // SETTINGS_HPP_
1113