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