1 /*
2 * Copyright (c) 2018, 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 #include "settings.hpp"
35
36 #include "common/array.hpp"
37 #include "common/code_utils.hpp"
38 #include "common/instance.hpp"
39 #include "common/locator_getters.hpp"
40 #include "common/num_utils.hpp"
41 #include "meshcop/dataset.hpp"
42 #include "thread/mle.hpp"
43
44 namespace ot {
45
46 RegisterLogModule("Settings");
47
48 //---------------------------------------------------------------------------------------------------------------------
49 // SettingsBase
50
51 // LCOV_EXCL_START
52
53 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
54
Log(Action aAction) const55 void SettingsBase::NetworkInfo::Log(Action aAction) const
56 {
57 LogInfo("%s NetworkInfo {rloc:0x%04x, extaddr:%s, role:%s, mode:0x%02x, version:%u, keyseq:0x%lx, ...",
58 ActionToString(aAction), GetRloc16(), GetExtAddress().ToString().AsCString(),
59 Mle::RoleToString(static_cast<Mle::DeviceRole>(GetRole())), GetDeviceMode(), GetVersion(),
60 ToUlong(GetKeySequence()));
61
62 LogInfo("... pid:0x%lx, mlecntr:0x%lx, maccntr:0x%lx, mliid:%s}", ToUlong(GetPreviousPartitionId()),
63 ToUlong(GetMleFrameCounter()), ToUlong(GetMacFrameCounter()), GetMeshLocalIid().ToString().AsCString());
64 }
65
Log(Action aAction) const66 void SettingsBase::ParentInfo::Log(Action aAction) const
67 {
68 LogInfo("%s ParentInfo {extaddr:%s, version:%u}", ActionToString(aAction), GetExtAddress().ToString().AsCString(),
69 GetVersion());
70 }
71
72 #if OPENTHREAD_FTD
Log(Action aAction) const73 void SettingsBase::ChildInfo::Log(Action aAction) const
74 {
75 LogInfo("%s ChildInfo {rloc:0x%04x, extaddr:%s, timeout:%lu, mode:0x%02x, version:%u}", ActionToString(aAction),
76 GetRloc16(), GetExtAddress().ToString().AsCString(), ToUlong(GetTimeout()), GetMode(), GetVersion());
77 }
78 #endif
79
80 #if OPENTHREAD_CONFIG_DUA_ENABLE
Log(Action aAction) const81 void SettingsBase::DadInfo::Log(Action aAction) const
82 {
83 LogInfo("%s DadInfo {DadCounter:%2d}", ActionToString(aAction), GetDadCounter());
84 }
85 #endif
86
87 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
LogPrefix(Action aAction,Key aKey,const Ip6::Prefix & aPrefix)88 void SettingsBase::LogPrefix(Action aAction, Key aKey, const Ip6::Prefix &aPrefix)
89 {
90 LogInfo("%s %s %s", ActionToString(aAction), KeyToString(aKey), aPrefix.ToString().AsCString());
91 }
92 #endif
93
94 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
Log(Action aAction) const95 void SettingsBase::SrpClientInfo::Log(Action aAction) const
96 {
97 LogInfo("%s SrpClientInfo {Server:[%s]:%u}", ActionToString(aAction), GetServerAddress().ToString().AsCString(),
98 GetServerPort());
99 }
100 #endif
101
102 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
Log(Action aAction) const103 void SettingsBase::SrpServerInfo::Log(Action aAction) const
104 {
105 LogInfo("%s SrpServerInfo {port:%u}", ActionToString(aAction), GetPort());
106 }
107 #endif
108
109 #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
SetId(const uint8_t * aId,uint16_t aLength)110 Error SettingsBase::BorderAgentId::SetId(const uint8_t *aId, uint16_t aLength)
111 {
112 Error error = kErrorNone;
113
114 VerifyOrExit(aLength == sizeof(mId), error = kErrorInvalidArgs);
115 memcpy(mId, aId, aLength);
116
117 exit:
118 return error;
119 }
120
Log(Action aAction) const121 void SettingsBase::BorderAgentId::Log(Action aAction) const
122 {
123 char buffer[sizeof(BorderAgentId) * 2 + 1];
124 StringWriter sw(buffer, sizeof(buffer));
125
126 sw.AppendHexBytes(GetId(), sizeof(BorderAgentId));
127 LogInfo("%s BorderAgentId {id:%s}", ActionToString(aAction), buffer);
128 }
129 #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
130
131 #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
132
133 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
ActionToString(Action aAction)134 const char *SettingsBase::ActionToString(Action aAction)
135 {
136 static const char *const kActionStrings[] = {
137 "Read", // (0) kActionRead
138 "Saved", // (1) kActionSave
139 "Re-saved", // (2) kActionResave
140 "Deleted", // (3) kActionDelete
141 #if OPENTHREAD_FTD
142 "Added", // (4) kActionAdd,
143 "Removed", // (5) kActionRemove,
144 "Deleted all" // (6) kActionDeleteAll
145 #endif
146 };
147
148 static_assert(0 == kActionRead, "kActionRead value is incorrect");
149 static_assert(1 == kActionSave, "kActionSave value is incorrect");
150 static_assert(2 == kActionResave, "kActionResave value is incorrect");
151 static_assert(3 == kActionDelete, "kActionDelete value is incorrect");
152 #if OPENTHREAD_FTD
153 static_assert(4 == kActionAdd, "kActionAdd value is incorrect");
154 static_assert(5 == kActionRemove, "kActionRemove value is incorrect");
155 static_assert(6 == kActionDeleteAll, "kActionDeleteAll value is incorrect");
156 #endif
157
158 return kActionStrings[aAction];
159 }
160 #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
161
162 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
KeyToString(Key aKey)163 const char *SettingsBase::KeyToString(Key aKey)
164 {
165 static const char *const kKeyStrings[] = {
166 "", // (0) (Unused)
167 "ActiveDataset", // (1) kKeyActiveDataset
168 "PendingDataset", // (2) kKeyPendingDataset
169 "NetworkInfo", // (3) kKeyNetworkInfo
170 "ParentInfo", // (4) kKeyParentInfo
171 "ChildInfo", // (5) kKeyChildInfo
172 "", // (6) Removed (previously auto-start).
173 "SlaacIidSecretKey", // (7) kKeySlaacIidSecretKey
174 "DadInfo", // (8) kKeyDadInfo
175 "", // (9) Removed (previously OMR prefix).
176 "", // (10) Removed (previously on-link prefix).
177 "SrpEcdsaKey", // (11) kKeySrpEcdsaKey
178 "SrpClientInfo", // (12) kKeySrpClientInfo
179 "SrpServerInfo", // (13) kKeySrpServerInfo
180 "", // (14) Removed (previously NAT64 prefix)
181 "BrUlaPrefix", // (15) kKeyBrUlaPrefix
182 "BrOnLinkPrefixes", // (16) kKeyBrOnLinkPrefixes
183 "BorderAgentId" // (17) kKeyBorderAgentId
184 };
185
186 static_assert(1 == kKeyActiveDataset, "kKeyActiveDataset value is incorrect");
187 static_assert(2 == kKeyPendingDataset, "kKeyPendingDataset value is incorrect");
188 static_assert(3 == kKeyNetworkInfo, "kKeyNetworkInfo value is incorrect");
189 static_assert(4 == kKeyParentInfo, "kKeyParentInfo value is incorrect");
190 static_assert(5 == kKeyChildInfo, "kKeyChildInfo value is incorrect");
191 static_assert(7 == kKeySlaacIidSecretKey, "kKeySlaacIidSecretKey value is incorrect");
192 static_assert(8 == kKeyDadInfo, "kKeyDadInfo value is incorrect");
193 static_assert(11 == kKeySrpEcdsaKey, "kKeySrpEcdsaKey value is incorrect");
194 static_assert(12 == kKeySrpClientInfo, "kKeySrpClientInfo value is incorrect");
195 static_assert(13 == kKeySrpServerInfo, "kKeySrpServerInfo value is incorrect");
196 static_assert(15 == kKeyBrUlaPrefix, "kKeyBrUlaPrefix value is incorrect");
197 static_assert(16 == kKeyBrOnLinkPrefixes, "kKeyBrOnLinkPrefixes is incorrect");
198 static_assert(17 == kKeyBorderAgentId, "kKeyBorderAgentId is incorrect");
199
200 static_assert(kLastKey == kKeyBorderAgentId, "kLastKey is not valid");
201
202 OT_ASSERT(aKey <= kLastKey);
203
204 return kKeyStrings[aKey];
205 }
206 #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
207
208 // LCOV_EXCL_STOP
209
210 //---------------------------------------------------------------------------------------------------------------------
211 // Settings
212
213 // This array contains sensitive keys that should be stored in the secure area.
214 const uint16_t Settings::kSensitiveKeys[] = {
215 SettingsBase::kKeyActiveDataset,
216 SettingsBase::kKeyPendingDataset,
217 SettingsBase::kKeySrpEcdsaKey,
218 };
219
Init(void)220 void Settings::Init(void) { Get<SettingsDriver>().Init(kSensitiveKeys, GetArrayLength(kSensitiveKeys)); }
221
Deinit(void)222 void Settings::Deinit(void) { Get<SettingsDriver>().Deinit(); }
223
Wipe(void)224 void Settings::Wipe(void)
225 {
226 Get<SettingsDriver>().Wipe();
227 LogInfo("Wiped all info");
228 }
229
KeyForDatasetType(MeshCoP::Dataset::Type aType)230 Settings::Key Settings::KeyForDatasetType(MeshCoP::Dataset::Type aType)
231 {
232 return (aType == MeshCoP::Dataset::kActive) ? kKeyActiveDataset : kKeyPendingDataset;
233 }
234
SaveOperationalDataset(MeshCoP::Dataset::Type aType,const MeshCoP::Dataset & aDataset)235 Error Settings::SaveOperationalDataset(MeshCoP::Dataset::Type aType, const MeshCoP::Dataset &aDataset)
236 {
237 Key key = KeyForDatasetType(aType);
238 Error error = Get<SettingsDriver>().Set(key, aDataset.GetBytes(), aDataset.GetSize());
239
240 Log(kActionSave, error, key);
241
242 return error;
243 }
244
ReadOperationalDataset(MeshCoP::Dataset::Type aType,MeshCoP::Dataset & aDataset) const245 Error Settings::ReadOperationalDataset(MeshCoP::Dataset::Type aType, MeshCoP::Dataset &aDataset) const
246 {
247 Error error = kErrorNone;
248 uint16_t length = MeshCoP::Dataset::kMaxSize;
249
250 SuccessOrExit(error = Get<SettingsDriver>().Get(KeyForDatasetType(aType), aDataset.GetBytes(), &length));
251 VerifyOrExit(length <= MeshCoP::Dataset::kMaxSize, error = kErrorNotFound);
252
253 aDataset.SetSize(length);
254
255 exit:
256 return error;
257 }
258
DeleteOperationalDataset(MeshCoP::Dataset::Type aType)259 Error Settings::DeleteOperationalDataset(MeshCoP::Dataset::Type aType)
260 {
261 Key key = KeyForDatasetType(aType);
262 Error error = Get<SettingsDriver>().Delete(key);
263
264 Log(kActionDelete, error, key);
265
266 return error;
267 }
268
269 #if OPENTHREAD_FTD
AddChildInfo(const ChildInfo & aChildInfo)270 Error Settings::AddChildInfo(const ChildInfo &aChildInfo)
271 {
272 Error error = Get<SettingsDriver>().Add(kKeyChildInfo, &aChildInfo, sizeof(aChildInfo));
273
274 Log(kActionAdd, error, kKeyChildInfo, &aChildInfo);
275
276 return error;
277 }
278
DeleteAllChildInfo(void)279 Error Settings::DeleteAllChildInfo(void)
280 {
281 Error error = Get<SettingsDriver>().Delete(kKeyChildInfo);
282
283 Log(kActionDeleteAll, error, kKeyChildInfo);
284
285 return error;
286 }
287
ChildInfoIterator(Instance & aInstance)288 Settings::ChildInfoIterator::ChildInfoIterator(Instance &aInstance)
289 : SettingsBase(aInstance)
290 , mIndex(0)
291 , mIsDone(false)
292 {
293 Read();
294 }
295
Advance(void)296 void Settings::ChildInfoIterator::Advance(void)
297 {
298 if (!mIsDone)
299 {
300 mIndex++;
301 Read();
302 }
303 }
304
Delete(void)305 Error Settings::ChildInfoIterator::Delete(void)
306 {
307 Error error = kErrorNone;
308
309 VerifyOrExit(!mIsDone, error = kErrorInvalidState);
310 SuccessOrExit(error = Get<SettingsDriver>().Delete(kKeyChildInfo, mIndex));
311
312 exit:
313 Log(kActionRemove, error, kKeyChildInfo, &mChildInfo);
314 return error;
315 }
316
Read(void)317 void Settings::ChildInfoIterator::Read(void)
318 {
319 uint16_t length = sizeof(ChildInfo);
320 Error error;
321
322 mChildInfo.Init();
323 SuccessOrExit(
324 error = Get<SettingsDriver>().Get(kKeyChildInfo, mIndex, reinterpret_cast<uint8_t *>(&mChildInfo), &length));
325
326 exit:
327 Log(kActionRead, error, kKeyChildInfo, &mChildInfo);
328 mIsDone = (error != kErrorNone);
329 }
330 #endif // OPENTHREAD_FTD
331
332 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
AddOrUpdateBrOnLinkPrefix(const BrOnLinkPrefix & aBrOnLinkPrefix)333 Error Settings::AddOrUpdateBrOnLinkPrefix(const BrOnLinkPrefix &aBrOnLinkPrefix)
334 {
335 Error error = kErrorNone;
336 int index = 0;
337 BrOnLinkPrefix brPrefix;
338 bool didUpdate = false;
339
340 while (ReadBrOnLinkPrefix(index, brPrefix) == kErrorNone)
341 {
342 if (brPrefix.GetPrefix() == aBrOnLinkPrefix.GetPrefix())
343 {
344 if (brPrefix.GetLifetime() == aBrOnLinkPrefix.GetLifetime())
345 {
346 // Existing entry fully matches `aBrOnLinkPrefix`.
347 // No need to make any changes.
348 ExitNow();
349 }
350
351 SuccessOrExit(error = Get<SettingsDriver>().Delete(kKeyBrOnLinkPrefixes, index));
352 didUpdate = true;
353 break;
354 }
355
356 index++;
357 }
358
359 SuccessOrExit(error = Get<SettingsDriver>().Add(kKeyBrOnLinkPrefixes, &aBrOnLinkPrefix, sizeof(BrOnLinkPrefix)));
360 brPrefix.Log(didUpdate ? "Updated" : "Added");
361
362 exit:
363 return error;
364 }
365
RemoveBrOnLinkPrefix(const Ip6::Prefix & aPrefix)366 Error Settings::RemoveBrOnLinkPrefix(const Ip6::Prefix &aPrefix)
367 {
368 Error error = kErrorNotFound;
369 BrOnLinkPrefix brPrefix;
370
371 for (int index = 0; ReadBrOnLinkPrefix(index, brPrefix) == kErrorNone; index++)
372 {
373 if (brPrefix.GetPrefix() == aPrefix)
374 {
375 SuccessOrExit(error = Get<SettingsDriver>().Delete(kKeyBrOnLinkPrefixes, index));
376 brPrefix.Log("Removed");
377 break;
378 }
379 }
380
381 exit:
382 return error;
383 }
384
DeleteAllBrOnLinkPrefixes(void)385 Error Settings::DeleteAllBrOnLinkPrefixes(void) { return Get<SettingsDriver>().Delete(kKeyBrOnLinkPrefixes); }
386
ReadBrOnLinkPrefix(int aIndex,BrOnLinkPrefix & aBrOnLinkPrefix)387 Error Settings::ReadBrOnLinkPrefix(int aIndex, BrOnLinkPrefix &aBrOnLinkPrefix)
388 {
389 uint16_t length = sizeof(BrOnLinkPrefix);
390
391 aBrOnLinkPrefix.Init();
392
393 return Get<SettingsDriver>().Get(kKeyBrOnLinkPrefixes, aIndex, &aBrOnLinkPrefix, &length);
394 }
395
Log(const char * aActionText) const396 void Settings::BrOnLinkPrefix::Log(const char *aActionText) const
397 {
398 OT_UNUSED_VARIABLE(aActionText);
399
400 LogInfo("%s %s entry {prefix:%s,lifetime:%lu}", aActionText, KeyToString(kKeyBrOnLinkPrefixes),
401 GetPrefix().ToString().AsCString(), ToUlong(GetLifetime()));
402 }
403
404 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
405
ReadEntry(Key aKey,void * aValue,uint16_t aMaxLength) const406 Error Settings::ReadEntry(Key aKey, void *aValue, uint16_t aMaxLength) const
407 {
408 Error error;
409 uint16_t length = aMaxLength;
410
411 error = Get<SettingsDriver>().Get(aKey, aValue, &length);
412 Log(kActionRead, error, aKey, aValue);
413
414 return error;
415 }
416
SaveEntry(Key aKey,const void * aValue,void * aPrev,uint16_t aLength)417 Error Settings::SaveEntry(Key aKey, const void *aValue, void *aPrev, uint16_t aLength)
418 {
419 Error error = kErrorNone;
420 uint16_t readLength = aLength;
421 Action action = kActionSave;
422
423 if ((Get<SettingsDriver>().Get(aKey, aPrev, &readLength) == kErrorNone) && (readLength == aLength) &&
424 (memcmp(aValue, aPrev, aLength) == 0))
425 {
426 action = kActionResave;
427 }
428 else
429 {
430 error = Get<SettingsDriver>().Set(aKey, aValue, aLength);
431 }
432
433 Log(action, error, aKey, aValue);
434
435 return error;
436 }
437
DeleteEntry(Key aKey)438 Error Settings::DeleteEntry(Key aKey)
439 {
440 Error error = Get<SettingsDriver>().Delete(aKey);
441
442 Log(kActionDelete, error, aKey);
443
444 return error;
445 }
446
Log(Action aAction,Error aError,Key aKey,const void * aValue)447 void Settings::Log(Action aAction, Error aError, Key aKey, const void *aValue)
448 {
449 OT_UNUSED_VARIABLE(aAction);
450 OT_UNUSED_VARIABLE(aKey);
451 OT_UNUSED_VARIABLE(aError);
452 OT_UNUSED_VARIABLE(aValue);
453
454 if (aError != kErrorNone)
455 {
456 // Log error if log level is at "warn" or higher.
457
458 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
459 const char *actionText = "";
460
461 switch (aAction)
462 {
463 case kActionSave:
464 case kActionResave:
465 actionText = "saving";
466 break;
467
468 case kActionDelete:
469 VerifyOrExit(aError != kErrorNotFound);
470 actionText = "deleting";
471 break;
472
473 #if OPENTHREAD_FTD
474 case kActionAdd:
475 actionText = "adding";
476 break;
477
478 case kActionRemove:
479 VerifyOrExit(aError != kErrorNotFound);
480 actionText = "removing";
481 break;
482
483 case kActionDeleteAll:
484 VerifyOrExit(aError != kErrorNotFound);
485 actionText = "deleting all";
486 break;
487 #endif
488 case kActionRead:
489 ExitNow();
490 }
491
492 LogWarn("Error %s %s %s", ErrorToString(aError), actionText, KeyToString(aKey));
493
494 #endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
495
496 ExitNow();
497 }
498
499 // We reach here when `aError` is `kErrorNone`.
500 // Log success if log level is at "info" or higher.
501
502 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
503 if (aValue != nullptr)
504 {
505 switch (aKey)
506 {
507 case kKeyNetworkInfo:
508 reinterpret_cast<const NetworkInfo *>(aValue)->Log(aAction);
509 break;
510
511 case kKeyParentInfo:
512 reinterpret_cast<const ParentInfo *>(aValue)->Log(aAction);
513 break;
514
515 #if OPENTHREAD_FTD
516 case kKeyChildInfo:
517 reinterpret_cast<const ChildInfo *>(aValue)->Log(aAction);
518 break;
519 #endif
520
521 #if OPENTHREAD_CONFIG_DUA_ENABLE
522 case kKeyDadInfo:
523 reinterpret_cast<const DadInfo *>(aValue)->Log(aAction);
524 break;
525 #endif
526
527 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
528 case kKeyBrUlaPrefix:
529 LogPrefix(aAction, aKey, *reinterpret_cast<const Ip6::Prefix *>(aValue));
530 break;
531 #endif
532
533 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
534 case kKeySrpClientInfo:
535 reinterpret_cast<const SrpClientInfo *>(aValue)->Log(aAction);
536 break;
537 #endif
538
539 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
540 case kKeySrpServerInfo:
541 reinterpret_cast<const SrpServerInfo *>(aValue)->Log(aAction);
542 break;
543 #endif
544
545 #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
546 case kKeyBorderAgentId:
547 reinterpret_cast<const BorderAgentId *>(aValue)->Log(aAction);
548 break;
549 #endif
550
551 default:
552 // For any other keys, we do not want to include the value
553 // in the log, so even if it is given we set `aValue` to
554 // `nullptr`. This ensures that we just log the action and
555 // the key.
556 aValue = nullptr;
557 break;
558 }
559 }
560
561 if (aValue == nullptr)
562 {
563 LogInfo("%s %s", ActionToString(aAction), KeyToString(aKey));
564 }
565 #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
566
567 exit:
568 return;
569 }
570
571 } // namespace ot
572
573 //---------------------------------------------------------------------------------------------------------------------
574 // Default/weak implementation of settings platform APIs
575
otPlatSettingsSetCriticalKeys(otInstance * aInstance,const uint16_t * aKeys,uint16_t aKeysLength)576 OT_TOOL_WEAK void otPlatSettingsSetCriticalKeys(otInstance *aInstance, const uint16_t *aKeys, uint16_t aKeysLength)
577 {
578 OT_UNUSED_VARIABLE(aInstance);
579 OT_UNUSED_VARIABLE(aKeys);
580 OT_UNUSED_VARIABLE(aKeysLength);
581 }
582