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/border_agent.h>
40 #include <openthread/platform/settings.h>
41 
42 #include "common/clearable.hpp"
43 #include "common/encoding.hpp"
44 #include "common/equatable.hpp"
45 #include "common/locator.hpp"
46 #include "common/log.hpp"
47 #include "common/non_copyable.hpp"
48 #include "common/settings_driver.hpp"
49 #include "crypto/ecdsa.hpp"
50 #include "mac/mac_types.hpp"
51 #include "meshcop/dataset.hpp"
52 #include "net/ip6_address.hpp"
53 #include "thread/version.hpp"
54 #include "utils/flash.hpp"
55 #include "utils/slaac_address.hpp"
56 
57 namespace ot {
58 
59 class Settings;
60 
61 /**
62  * This class defines the base class used by `Settings` and `Settings::ChildInfoIterator`.
63  *
64  * This class provides structure definitions for different settings keys.
65  *
66  */
67 class SettingsBase : public InstanceLocator
68 {
69 protected:
70     enum Action : uint8_t
71     {
72         kActionRead,
73         kActionSave,
74         kActionResave,
75         kActionDelete,
76 #if OPENTHREAD_FTD
77         kActionAdd,
78         kActionRemove,
79         kActionDeleteAll,
80 #endif
81     };
82 
83 public:
84     /**
85      * Rules for updating existing value structures.
86      *
87      * 1. Modifying existing key value fields in settings MUST only be
88      *    done by appending new fields.  Existing fields MUST NOT be
89      *    deleted or modified in any way.
90      *
91      * 2. To support backward compatibility (rolling back to an older
92      *    software version), code reading and processing key values MUST
93      *    process key values that have longer length.  Additionally, newer
94      *    versions MUST update/maintain values in existing key value
95      *    fields.
96      *
97      * 3. To support forward compatibility (rolling forward to a newer
98      *    software version), code reading and processing key values MUST
99      *    process key values that have shorter length.
100      *
101      * 4. New Key IDs may be defined in the future with the understanding
102      *    that such key values are not backward compatible.
103      *
104      */
105 
106     /**
107      * This enumeration defines the keys of settings.
108      *
109      */
110     enum Key : uint16_t
111     {
112         kKeyActiveDataset     = OT_SETTINGS_KEY_ACTIVE_DATASET,
113         kKeyPendingDataset    = OT_SETTINGS_KEY_PENDING_DATASET,
114         kKeyNetworkInfo       = OT_SETTINGS_KEY_NETWORK_INFO,
115         kKeyParentInfo        = OT_SETTINGS_KEY_PARENT_INFO,
116         kKeyChildInfo         = OT_SETTINGS_KEY_CHILD_INFO,
117         kKeySlaacIidSecretKey = OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY,
118         kKeyDadInfo           = OT_SETTINGS_KEY_DAD_INFO,
119         kKeySrpEcdsaKey       = OT_SETTINGS_KEY_SRP_ECDSA_KEY,
120         kKeySrpClientInfo     = OT_SETTINGS_KEY_SRP_CLIENT_INFO,
121         kKeySrpServerInfo     = OT_SETTINGS_KEY_SRP_SERVER_INFO,
122         kKeyBrUlaPrefix       = OT_SETTINGS_KEY_BR_ULA_PREFIX,
123         kKeyBrOnLinkPrefixes  = OT_SETTINGS_KEY_BR_ON_LINK_PREFIXES,
124         kKeyBorderAgentId     = OT_SETTINGS_KEY_BORDER_AGENT_ID,
125     };
126 
127     static constexpr Key kLastKey = kKeyBorderAgentId; ///< The last (numerically) enumerator value in `Key`.
128 
129     static_assert(static_cast<uint16_t>(kLastKey) < static_cast<uint16_t>(OT_SETTINGS_KEY_VENDOR_RESERVED_MIN),
130                   "Core settings keys overlap with vendor reserved keys");
131 
132     /**
133      * This structure represents the device's own network information for settings storage.
134      *
135      */
136     OT_TOOL_PACKED_BEGIN
137     class NetworkInfo : private Clearable<NetworkInfo>
138     {
139         friend class Settings;
140         friend class Clearable<NetworkInfo>;
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(kThreadVersion1p1);
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         friend class Clearable<ParentInfo>;
348 
349     public:
350         static constexpr Key kKey = kKeyParentInfo; ///< The associated key.
351 
352         /**
353          * This method initializes the `ParentInfo` object.
354          *
355          */
Init(void)356         void Init(void)
357         {
358             Clear();
359             SetVersion(kThreadVersion1p1);
360         }
361 
362         /**
363          * This method returns the extended address.
364          *
365          * @returns The extended address.
366          *
367          */
GetExtAddress(void) const368         const Mac::ExtAddress &GetExtAddress(void) const { return mExtAddress; }
369 
370         /**
371          * This method sets the extended address.
372          *
373          * @param[in] aExtAddress  The extended address.
374          *
375          */
SetExtAddress(const Mac::ExtAddress & aExtAddress)376         void SetExtAddress(const Mac::ExtAddress &aExtAddress) { mExtAddress = aExtAddress; }
377 
378         /**
379          * This method returns the Thread version.
380          *
381          * @returns The Thread version.
382          *
383          */
GetVersion(void) const384         uint16_t GetVersion(void) const { return Encoding::LittleEndian::HostSwap16(mVersion); }
385 
386         /**
387          * This method sets the Thread version.
388          *
389          * @param[in] aVersion  The Thread version.
390          *
391          */
SetVersion(uint16_t aVersion)392         void SetVersion(uint16_t aVersion) { mVersion = Encoding::LittleEndian::HostSwap16(aVersion); }
393 
394     private:
395         void Log(Action aAction) const;
396 
397         Mac::ExtAddress mExtAddress; ///< Extended Address
398         uint16_t        mVersion;    ///< Version
399     } OT_TOOL_PACKED_END;
400 
401 #if OPENTHREAD_FTD
402     /**
403      * This structure represents the child information for settings storage.
404      *
405      */
406     OT_TOOL_PACKED_BEGIN
407     class ChildInfo
408     {
409         friend class Settings;
410 
411     public:
412         static constexpr Key kKey = kKeyChildInfo; ///< The associated key.
413 
414         /**
415          * This method clears the struct object (setting all the fields to zero).
416          *
417          */
Init(void)418         void Init(void)
419         {
420             memset(this, 0, sizeof(*this));
421             SetVersion(kThreadVersion1p1);
422         }
423 
424         /**
425          * This method returns the extended address.
426          *
427          * @returns The extended address.
428          *
429          */
GetExtAddress(void) const430         const Mac::ExtAddress &GetExtAddress(void) const { return mExtAddress; }
431 
432         /**
433          * This method sets the extended address.
434          *
435          * @param[in] aExtAddress  The extended address.
436          *
437          */
SetExtAddress(const Mac::ExtAddress & aExtAddress)438         void SetExtAddress(const Mac::ExtAddress &aExtAddress) { mExtAddress = aExtAddress; }
439 
440         /**
441          * This method returns the child timeout.
442          *
443          * @returns The child timeout.
444          *
445          */
GetTimeout(void) const446         uint32_t GetTimeout(void) const { return Encoding::LittleEndian::HostSwap32(mTimeout); }
447 
448         /**
449          * This method sets the child timeout.
450          *
451          * @param[in] aTimeout  The child timeout.
452          *
453          */
SetTimeout(uint32_t aTimeout)454         void SetTimeout(uint32_t aTimeout) { mTimeout = Encoding::LittleEndian::HostSwap32(aTimeout); }
455 
456         /**
457          * This method returns the RLOC16.
458          *
459          * @returns The RLOC16.
460          *
461          */
GetRloc16(void) const462         uint16_t GetRloc16(void) const { return Encoding::LittleEndian::HostSwap16(mRloc16); }
463 
464         /**
465          * This method sets the RLOC16.
466          *
467          * @param[in] aRloc16  The RLOC16.
468          *
469          */
SetRloc16(uint16_t aRloc16)470         void SetRloc16(uint16_t aRloc16) { mRloc16 = Encoding::LittleEndian::HostSwap16(aRloc16); }
471 
472         /**
473          * This method returns the Thread device mode.
474          *
475          * @returns The Thread device mode.
476          *
477          */
GetMode(void) const478         uint8_t GetMode(void) const { return mMode; }
479 
480         /**
481          * This method sets the Thread device mode.
482          *
483          * @param[in] aMode  The Thread device mode.
484          *
485          */
SetMode(uint8_t aMode)486         void SetMode(uint8_t aMode) { mMode = aMode; }
487 
488         /**
489          * This method returns the Thread version.
490          *
491          * @returns The Thread version.
492          *
493          */
GetVersion(void) const494         uint16_t GetVersion(void) const { return Encoding::LittleEndian::HostSwap16(mVersion); }
495 
496         /**
497          * This method sets the Thread version.
498          *
499          * @param[in] aVersion  The Thread version.
500          *
501          */
SetVersion(uint16_t aVersion)502         void SetVersion(uint16_t aVersion) { mVersion = Encoding::LittleEndian::HostSwap16(aVersion); }
503 
504     private:
505         void Log(Action aAction) const;
506 
507         Mac::ExtAddress mExtAddress; ///< Extended Address
508         uint32_t        mTimeout;    ///< Timeout
509         uint16_t        mRloc16;     ///< RLOC16
510         uint8_t         mMode;       ///< The MLE device mode
511         uint16_t        mVersion;    ///< Version
512     } OT_TOOL_PACKED_END;
513 #endif // OPENTHREAD_FTD
514 
515 #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
516     /**
517      * This class defines constants and types for SLAAC IID Secret key settings.
518      *
519      */
520     class SlaacIidSecretKey
521     {
522     public:
523         static constexpr Key kKey = kKeySlaacIidSecretKey; ///< The associated key.
524 
525         typedef Utils::Slaac::IidSecretKey ValueType; ///< The associated value type.
526 
527     private:
528         SlaacIidSecretKey(void) = default;
529     };
530 #endif
531 
532 #if OPENTHREAD_CONFIG_DUA_ENABLE
533     /**
534      * This structure represents the duplicate address detection information for settings storage.
535      *
536      */
537     OT_TOOL_PACKED_BEGIN
538     class DadInfo : private Clearable<DadInfo>
539     {
540         friend class Settings;
541         friend class Clearable<DadInfo>;
542 
543     public:
544         static constexpr Key kKey = kKeyDadInfo; ///< The associated key.
545 
546         /**
547          * This method initializes the `DadInfo` object.
548          *
549          */
Init(void)550         void Init(void) { Clear(); }
551 
552         /**
553          * This method returns the Dad Counter.
554          *
555          * @returns The Dad Counter value.
556          *
557          */
GetDadCounter(void) const558         uint8_t GetDadCounter(void) const { return mDadCounter; }
559 
560         /**
561          * This method sets the Dad Counter.
562          *
563          * @param[in] aDadCounter The Dad Counter value.
564          *
565          */
SetDadCounter(uint8_t aDadCounter)566         void SetDadCounter(uint8_t aDadCounter) { mDadCounter = aDadCounter; }
567 
568     private:
569         void Log(Action aAction) const;
570 
571         uint8_t mDadCounter; ///< Dad Counter used to resolve address conflict in Thread 1.2 DUA feature.
572     } OT_TOOL_PACKED_END;
573 #endif // OPENTHREAD_CONFIG_DUA_ENABLE
574 
575 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
576     /**
577      * This class defines constants and types for BR ULA prefix settings.
578      *
579      */
580     class BrUlaPrefix
581     {
582     public:
583         static constexpr Key kKey = kKeyBrUlaPrefix; ///< The associated key.
584 
585         typedef Ip6::Prefix ValueType; ///< The associated value type.
586 
587     private:
588         BrUlaPrefix(void) = default;
589     };
590 
591     /**
592      * This class represents a BR on-link prefix entry for settings storage.
593      *
594      */
595     OT_TOOL_PACKED_BEGIN
596     class BrOnLinkPrefix : public Clearable<BrOnLinkPrefix>
597     {
598         friend class Settings;
599 
600     public:
601         static constexpr Key kKey = kKeyBrOnLinkPrefixes; ///< The associated key.
602 
603         /**
604          * This method initializes the `BrOnLinkPrefix` object.
605          *
606          */
Init(void)607         void Init(void) { Clear(); }
608 
609         /**
610          * This method gets the prefix.
611          *
612          * @returns The prefix.
613          *
614          */
GetPrefix(void) const615         const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
616 
617         /**
618          * This method set the prefix.
619          *
620          * @param[in] aPrefix   The prefix.
621          *
622          */
SetPrefix(const Ip6::Prefix & aPrefix)623         void SetPrefix(const Ip6::Prefix &aPrefix) { mPrefix = aPrefix; }
624 
625         /**
626          * This method gets the remaining prefix lifetime in seconds.
627          *
628          * @returns The prefix lifetime in seconds.
629          *
630          */
GetLifetime(void) const631         uint32_t GetLifetime(void) const { return mLifetime; }
632 
633         /**
634          * This method sets the the prefix lifetime.
635          *
636          * @param[in] aLifetime  The prefix lifetime in seconds.
637          *
638          */
SetLifetime(uint32_t aLifetime)639         void SetLifetime(uint32_t aLifetime) { mLifetime = aLifetime; }
640 
641     private:
642         void Log(const char *aActionText) const;
643 
644         Ip6::Prefix mPrefix;
645         uint32_t    mLifetime;
646     } OT_TOOL_PACKED_END;
647 
648 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
649 
650 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
651     /**
652      * This class defines constants and types for SRP ECDSA key settings.
653      *
654      */
655     class SrpEcdsaKey
656     {
657     public:
658         static constexpr Key kKey = kKeySrpEcdsaKey; ///< The associated key.
659 
660         typedef Crypto::Ecdsa::P256::KeyPair ValueType; ///< The associated value type.
661 
662     private:
663         SrpEcdsaKey(void) = default;
664     };
665 
666 #if OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
667     /**
668      * This structure represents the SRP client info (selected server address).
669      *
670      */
671     OT_TOOL_PACKED_BEGIN
672     class SrpClientInfo : private Clearable<SrpClientInfo>
673     {
674         friend class Settings;
675         friend class Clearable<SrpClientInfo>;
676 
677     public:
678         static constexpr Key kKey = kKeySrpClientInfo; ///< The associated key.
679 
680         /**
681          * This method initializes the `SrpClientInfo` object.
682          *
683          */
Init(void)684         void Init(void) { Clear(); }
685 
686         /**
687          * This method returns the server IPv6 address.
688          *
689          * @returns The server IPv6 address.
690          *
691          */
GetServerAddress(void) const692         const Ip6::Address &GetServerAddress(void) const { return mServerAddress; }
693 
694         /**
695          * This method sets the server IPv6 address.
696          *
697          * @param[in] aAddress  The server IPv6 address.
698          *
699          */
SetServerAddress(const Ip6::Address & aAddress)700         void SetServerAddress(const Ip6::Address &aAddress) { mServerAddress = aAddress; }
701 
702         /**
703          * This method returns the server port number.
704          *
705          * @returns The server port number.
706          *
707          */
GetServerPort(void) const708         uint16_t GetServerPort(void) const { return Encoding::LittleEndian::HostSwap16(mServerPort); }
709 
710         /**
711          * This method sets the server port number.
712          *
713          * @param[in] aPort  The server port number.
714          *
715          */
SetServerPort(uint16_t aPort)716         void SetServerPort(uint16_t aPort) { mServerPort = Encoding::LittleEndian::HostSwap16(aPort); }
717 
718     private:
719         void Log(Action aAction) const;
720 
721         Ip6::Address mServerAddress;
722         uint16_t     mServerPort; // (in little-endian encoding)
723     } OT_TOOL_PACKED_END;
724 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
725 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
726 
727 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
728     /**
729      * This structure represents the SRP server info.
730      *
731      */
732     OT_TOOL_PACKED_BEGIN
733     class SrpServerInfo : private Clearable<SrpServerInfo>
734     {
735         friend class Settings;
736         friend class Clearable<SrpServerInfo>;
737 
738     public:
739         static constexpr Key kKey = kKeySrpServerInfo; ///< The associated key.
740 
741         /**
742          * This method initializes the `SrpServerInfo` object.
743          *
744          */
Init(void)745         void Init(void) { Clear(); }
746 
747         /**
748          * This method returns the server port number.
749          *
750          * @returns The server port number.
751          *
752          */
GetPort(void) const753         uint16_t GetPort(void) const { return Encoding::LittleEndian::HostSwap16(mPort); }
754 
755         /**
756          * This method sets the server port number.
757          *
758          * @param[in] aPort  The server port number.
759          *
760          */
SetPort(uint16_t aPort)761         void SetPort(uint16_t aPort) { mPort = Encoding::LittleEndian::HostSwap16(aPort); }
762 
763     private:
764         void Log(Action aAction) const;
765 
766         uint16_t mPort; // (in little-endian encoding)
767     } OT_TOOL_PACKED_END;
768 #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
769 
770 #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
771     /**
772      * This structure represents the Border Agent ID.
773      *
774      */
775     OT_TOOL_PACKED_BEGIN
776     class BorderAgentId : private Clearable<BorderAgentId>
777     {
778         friend class Settings;
779         friend class Clearable<BorderAgentId>;
780 
781     public:
782         static constexpr Key     kKey    = kKeyBorderAgentId; ///< The associated key.
783         static constexpr uint8_t kLength = OT_BORDER_AGENT_ID_LENGTH;
784 
785         /**
786          * This method initializes the `BorderAgentId` object.
787          *
788          */
Init(void)789         void Init(void) { Clear(); }
790 
791         /**
792          * This method returns the Border Agent ID.
793          *
794          * @returns The Border Agent ID.
795          *
796          */
GetId(void) const797         const uint8_t *GetId(void) const { return mId; }
798 
799         /**
800          * This method returns the Border Agent ID.
801          *
802          * @returns The Border Agent ID.
803          *
804          */
GetId(void)805         uint8_t *GetId(void) { return mId; }
806 
807         /**
808          * This method sets the Border Agent ID.
809          *
810          * @retval kErrorInvalidArgs If `aLength` doesn't equal to `OT_BORDER_AGENT_ID_LENGTH`.
811          * @retval kErrorNone        If success.
812          *
813          */
814         Error SetId(const uint8_t *aId, uint16_t aLength);
815 
816     private:
817         void Log(Action aAction) const;
818 
819         uint8_t mId[kLength];
820     } OT_TOOL_PACKED_END;
821 #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
822 
823 protected:
SettingsBase(Instance & aInstance)824     explicit SettingsBase(Instance &aInstance)
825         : InstanceLocator(aInstance)
826     {
827     }
828 
829 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
830     static void LogPrefix(Action aAction, Key aKey, const Ip6::Prefix &aPrefix);
831 #endif
832 
833 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
834     static const char *KeyToString(Key aKey);
835 #endif
836 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
837     static const char *ActionToString(Action aAction);
838 #endif
839 };
840 
841 /**
842  * This class defines methods related to non-volatile storage of settings.
843  *
844  */
845 class Settings : public SettingsBase, private NonCopyable
846 {
847     class ChildInfoIteratorBuilder;
848 
849 public:
850     /**
851      * This constructor initializes a `Settings` object.
852      *
853      * @param[in]  aInstance     A reference to the OpenThread instance.
854      *
855      */
Settings(Instance & aInstance)856     explicit Settings(Instance &aInstance)
857         : SettingsBase(aInstance)
858     {
859     }
860 
861     /**
862      * This method initializes the platform settings (non-volatile) module.
863      *
864      * This should be called before any other method from this class.
865      *
866      */
867     void Init(void);
868 
869     /**
870      * This method de-initializes the platform settings (non-volatile) module.
871      *
872      * This method should be called when OpenThread instance is no longer in use.
873      *
874      */
875     void Deinit(void);
876 
877     /**
878      * This method removes all settings from the non-volatile store.
879      *
880      */
881     void Wipe(void);
882 
883     /**
884      * This method saves the Operational Dataset (active or pending).
885      *
886      * @param[in]   aType       The Dataset type (active or pending) to save.
887      * @param[in]   aDataset    A reference to a `Dataset` object to be saved.
888      *
889      * @retval kErrorNone             Successfully saved the Dataset.
890      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
891      *
892      */
893     Error SaveOperationalDataset(MeshCoP::Dataset::Type aType, const MeshCoP::Dataset &aDataset);
894 
895     /**
896      * This method reads the Operational Dataset (active or pending).
897      *
898      * @param[in]   aType            The Dataset type (active or pending) to read.
899      * @param[out]  aDataset         A reference to a `Dataset` object to output the read content.
900      *
901      * @retval kErrorNone             Successfully read the Dataset.
902      * @retval kErrorNotFound         No corresponding value in the setting store.
903      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
904      *
905      */
906     Error ReadOperationalDataset(MeshCoP::Dataset::Type aType, MeshCoP::Dataset &aDataset) const;
907 
908     /**
909      * This method deletes the Operational Dataset (active/pending) from settings.
910      *
911      * @param[in]   aType            The Dataset type (active or pending) to delete.
912      *
913      * @retval kErrorNone            Successfully deleted the Dataset.
914      * @retval kErrorNotImplemented  The platform does not implement settings functionality.
915      *
916      */
917     Error DeleteOperationalDataset(MeshCoP::Dataset::Type aType);
918 
919     /**
920      * This template method reads a specified settings entry.
921      *
922      * The template type `EntryType` specifies the entry's value data structure. It must provide the following:
923      *
924      *  - It must provide a constant `EntryType::kKey` to specify the associated entry settings key.
925      *  - It must provide method `Init()` to initialize the `aEntry` object.
926      *
927      * This version of `Read<EntryType>` is intended for use with entries that define a data structure which represents
928      * the entry's value, e.g., `NetworkInfo`, `ParentInfo`, `DadInfo`, etc.
929      *
930      * @tparam EntryType              The settings entry type.
931      *
932      * @param[out] aEntry             A reference to a entry data structure to output the read content.
933      *
934      * @retval kErrorNone             Successfully read the entry.
935      * @retval kErrorNotFound         No corresponding value in the setting store.
936      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
937      *
938      */
Read(EntryType & aEntry) const939     template <typename EntryType> Error Read(EntryType &aEntry) const
940     {
941         aEntry.Init();
942 
943         return ReadEntry(EntryType::kKey, &aEntry, sizeof(EntryType));
944     }
945 
946     /**
947      * This template method reads a specified settings entry.
948      *
949      * The template type `EntryType` provides information about the entry's value type. It must provide the following:
950      *
951      *  - It must provide a constant `EntryType::kKey` to specify the associated entry settings key.
952      *  - It must provide a nested type `EntryType::ValueType` to specify the associated entry value type.
953      *
954      * This version of `Read<EntryType>` is intended for use with entries that have a simple entry value type (which can
955      * be represented by an existing type), e.g., `OmrPrefix` (using `Ip6::Prefix` as the value type).
956      *
957      * @tparam EntryType              The settings entry type.
958      *
959      * @param[out] aValue             A reference to a value type object to output the read content.
960      *
961      * @retval kErrorNone             Successfully read the value.
962      * @retval kErrorNotFound         No corresponding value in the setting store.
963      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
964      *
965      */
Read(typename EntryType::ValueType & aValue) const966     template <typename EntryType> Error Read(typename EntryType::ValueType &aValue) const
967     {
968         return ReadEntry(EntryType::kKey, &aValue, sizeof(typename EntryType::ValueType));
969     }
970 
971     /**
972      * This template method saves a specified settings entry.
973      *
974      * The template type `EntryType` specifies the entry's value data structure. It must provide the following:
975      *
976      *  - It must provide a constant `EntryType::kKey` to specify the associated entry settings key.
977      *
978      * This version of `Save<EntryType>` is intended for use with entries that define a data structure which represents
979      * the entry's value, e.g., `NetworkInfo`, `ParentInfo`, `DadInfo`, etc.
980      *
981      * @tparam EntryType              The settings entry type.
982      *
983      * @param[in] aEntry              The entry value to be saved.
984      *
985      * @retval kErrorNone             Successfully saved Network Info in settings.
986      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
987      *
988      */
Save(const EntryType & aEntry)989     template <typename EntryType> Error Save(const EntryType &aEntry)
990     {
991         EntryType prev;
992 
993         return SaveEntry(EntryType::kKey, &aEntry, &prev, sizeof(EntryType));
994     }
995 
996     /**
997      * This template method saves a specified settings entry.
998      *
999      * The template type `EntryType` provides information about the entry's value type. It must provide the following:
1000      *
1001      *  - It must provide a constant `EntryType::kKey` to specify the associated entry settings key.
1002      *  - It must provide a nested type `EntryType::ValueType` to specify the associated entry value type.
1003      *
1004      * This version of `Save<EntryType>` is intended for use with entries that have a simple entry value type (which can
1005      * be represented by an existing type), e.g., `OmrPrefix` (using `Ip6::Prefix` as the value type).
1006      *
1007      * @tparam EntryType              The settings entry type.
1008      *
1009      * @param[in] aValue              The entry value to be saved.
1010      *
1011      * @retval kErrorNone             Successfully saved Network Info in settings.
1012      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
1013      *
1014      */
Save(const typename EntryType::ValueType & aValue)1015     template <typename EntryType> Error Save(const typename EntryType::ValueType &aValue)
1016     {
1017         typename EntryType::ValueType prev;
1018 
1019         return SaveEntry(EntryType::kKey, &aValue, &prev, sizeof(typename EntryType::ValueType));
1020     }
1021 
1022     /**
1023      * This template method deletes a specified setting entry.
1024      *
1025      * The template type `EntryType` provides information about the entry's key.
1026      *
1027      *  - It must provide a constant `EntryType::kKey` to specify the associated entry settings key.
1028      *
1029      * @tparam EntryType             The settings entry type.
1030      *
1031      * @retval kErrorNone            Successfully deleted the value.
1032      * @retval kErrorNotImplemented  The platform does not implement settings functionality.
1033      *
1034      */
Delete(void)1035     template <typename EntryType> Error Delete(void) { return DeleteEntry(EntryType::kKey); }
1036 
1037 #if OPENTHREAD_FTD
1038     /**
1039      * This method adds a Child Info entry to settings.
1040      *
1041      * @note Child Info is a list-based settings property and can contain multiple entries.
1042      *
1043      * @param[in]   aChildInfo            A reference to a `ChildInfo` structure to be saved/added.
1044      *
1045      * @retval kErrorNone             Successfully saved the Child Info in settings.
1046      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
1047      *
1048      */
1049     Error AddChildInfo(const ChildInfo &aChildInfo);
1050 
1051     /**
1052      * This method deletes all Child Info entries from the settings.
1053      *
1054      * @note Child Info is a list-based settings property and can contain multiple entries.
1055      *
1056      * @retval kErrorNone            Successfully deleted the value.
1057      * @retval kErrorNotImplemented  The platform does not implement settings functionality.
1058      *
1059      */
1060     Error DeleteAllChildInfo(void);
1061 
1062     /**
1063      * This method enables range-based `for` loop iteration over all child info entries in the `Settings`.
1064      *
1065      * This method should be used as follows:
1066      *
1067      *     for (const ChildInfo &childInfo : Get<Settings>().IterateChildInfo()) { ... }
1068      *
1069      *
1070      * @returns A ChildInfoIteratorBuilder instance.
1071      *
1072      */
IterateChildInfo(void)1073     ChildInfoIteratorBuilder IterateChildInfo(void) { return ChildInfoIteratorBuilder(GetInstance()); }
1074 
1075     /**
1076      * This class defines an iterator to access all Child Info entries in the settings.
1077      *
1078      */
1079     class ChildInfoIterator : public SettingsBase, public Unequatable<ChildInfoIterator>
1080     {
1081         friend class ChildInfoIteratorBuilder;
1082 
1083     public:
1084         /**
1085          * This constructor initializes a `ChildInfoInterator` object.
1086          *
1087          * @param[in]  aInstance  A reference to the OpenThread instance.
1088          *
1089          */
1090         explicit ChildInfoIterator(Instance &aInstance);
1091 
1092         /**
1093          * This method indicates whether there are no more Child Info entries in the list (iterator has reached end of
1094          * the list), or the current entry is valid.
1095          *
1096          * @retval TRUE   There are no more entries in the list (reached end of the list).
1097          * @retval FALSE  The current entry is valid.
1098          *
1099          */
IsDone(void) const1100         bool IsDone(void) const { return mIsDone; }
1101 
1102         /**
1103          * This method overloads operator `++` (pre-increment) to advance the iterator to move to the next Child Info
1104          * entry in the list (if any).
1105          *
1106          */
operator ++(void)1107         void operator++(void) { Advance(); }
1108 
1109         /**
1110          * This method overloads operator `++` (post-increment) to advance the iterator to move to the next Child Info
1111          * entry in the list (if any).
1112          *
1113          */
operator ++(int)1114         void operator++(int) { Advance(); }
1115 
1116         /**
1117          * This method gets the Child Info corresponding to the current iterator entry in the list.
1118          *
1119          * @note This method should be used only if `IsDone()` is returning FALSE indicating that the iterator is
1120          * pointing to a valid entry.
1121          *
1122          * @returns A reference to `ChildInfo` structure corresponding to current iterator entry.
1123          *
1124          */
GetChildInfo(void) const1125         const ChildInfo &GetChildInfo(void) const { return mChildInfo; }
1126 
1127         /**
1128          * This method deletes the current Child Info entry.
1129          *
1130          * @retval kErrorNone            The entry was deleted successfully.
1131          * @retval kErrorInvalidState    The entry is not valid (iterator has reached end of list).
1132          * @retval kErrorNotImplemented  The platform does not implement settings functionality.
1133          *
1134          */
1135         Error Delete(void);
1136 
1137         /**
1138          * This method overloads the `*` dereference operator and gets a reference to `ChildInfo` entry to which the
1139          * iterator is currently pointing.
1140          *
1141          * @note This method should be used only if `IsDone()` is returning FALSE indicating that the iterator is
1142          * pointing to a valid entry.
1143          *
1144          *
1145          * @returns A reference to the `ChildInfo` entry currently pointed by the iterator.
1146          *
1147          */
operator *(void) const1148         const ChildInfo &operator*(void) const { return mChildInfo; }
1149 
1150         /**
1151          * This method overloads operator `==` to evaluate whether or not two iterator instances are equal.
1152          *
1153          * @param[in]  aOther  The other iterator to compare with.
1154          *
1155          * @retval TRUE   If the two iterator objects are equal
1156          * @retval FALSE  If the two iterator objects are not equal.
1157          *
1158          */
operator ==(const ChildInfoIterator & aOther) const1159         bool operator==(const ChildInfoIterator &aOther) const
1160         {
1161             return (mIsDone && aOther.mIsDone) || (!mIsDone && !aOther.mIsDone && (mIndex == aOther.mIndex));
1162         }
1163 
1164     private:
1165         enum IteratorType : uint8_t
1166         {
1167             kEndIterator,
1168         };
1169 
ChildInfoIterator(Instance & aInstance,IteratorType)1170         ChildInfoIterator(Instance &aInstance, IteratorType)
1171             : SettingsBase(aInstance)
1172             , mIndex(0)
1173             , mIsDone(true)
1174         {
1175         }
1176 
1177         void Advance(void);
1178         void Read(void);
1179 
1180         ChildInfo mChildInfo;
1181         uint16_t  mIndex;
1182         bool      mIsDone;
1183     };
1184 #endif // OPENTHREAD_FTD
1185 
1186 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
1187     /**
1188      * This method adds or updates an on-link prefix.
1189      *
1190      * If there is no matching entry (matching the same `GetPrefix()`) saved in `Settings`, the new entry will be added.
1191      * If there is matching entry, it will be updated to the new @p aPrefix.
1192      *
1193      * @param[in] aBrOnLinkPrefix    The on-link prefix to save (add or updated).
1194      *
1195      * @retval kErrorNone             Successfully added or updated the entry in settings.
1196      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
1197      *
1198      */
1199     Error AddOrUpdateBrOnLinkPrefix(const BrOnLinkPrefix &aBrOnLinkPrefix);
1200 
1201     /**
1202      * This method removes an on-link prefix entry matching a given prefix.
1203      *
1204      * @param[in] aPrefix            The prefix to remove
1205      *
1206      * @retval kErrorNone            Successfully removed the matching entry in settings.
1207      * @retval kErrorNotImplemented  The platform does not implement settings functionality.
1208      *
1209      */
1210     Error RemoveBrOnLinkPrefix(const Ip6::Prefix &aPrefix);
1211 
1212     /**
1213      * This method deletes all on-link prefix entries from the settings.
1214      *
1215      * @retval kErrorNone            Successfully deleted the entries.
1216      * @retval kErrorNotImplemented  The platform does not implement settings functionality.
1217      *
1218      */
1219     Error DeleteAllBrOnLinkPrefixes(void);
1220 
1221     /**
1222      * This method retrieves an entry from on-link prefixes list at a given index.
1223      *
1224      * @param[in]  aIndex            The index to read.
1225      * @param[out] aBrOnLinkPrefix   A reference to `BrOnLinkPrefix` to output the read value.
1226      *
1227      * @retval kErrorNone             Successfully read the value.
1228      * @retval kErrorNotFound         No corresponding value in the setting store.
1229      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
1230      *
1231      */
1232     Error ReadBrOnLinkPrefix(int aIndex, BrOnLinkPrefix &aBrOnLinkPrefix);
1233 
1234 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
1235 
1236 private:
1237 #if OPENTHREAD_FTD
1238     class ChildInfoIteratorBuilder : public InstanceLocator
1239     {
1240     public:
ChildInfoIteratorBuilder(Instance & aInstance)1241         explicit ChildInfoIteratorBuilder(Instance &aInstance)
1242             : InstanceLocator(aInstance)
1243         {
1244         }
1245 
begin(void)1246         ChildInfoIterator begin(void) { return ChildInfoIterator(GetInstance()); }
end(void)1247         ChildInfoIterator end(void) { return ChildInfoIterator(GetInstance(), ChildInfoIterator::kEndIterator); }
1248     };
1249 #endif
1250 
1251     static Key KeyForDatasetType(MeshCoP::Dataset::Type aType);
1252 
1253     Error ReadEntry(Key aKey, void *aValue, uint16_t aMaxLength) const;
1254     Error SaveEntry(Key aKey, const void *aValue, void *aPrev, uint16_t aLength);
1255     Error DeleteEntry(Key aKey);
1256 
1257     static void Log(Action aAction, Error aError, Key aKey, const void *aValue = nullptr);
1258 
1259     static const uint16_t kSensitiveKeys[];
1260 };
1261 
1262 } // namespace ot
1263 
1264 #endif // SETTINGS_HPP_
1265