1 /*
2 * Copyright (c) 2022, 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 implements Network Name management.
32 *
33 */
34
35 #include "network_name.hpp"
36
37 #include "common/locator_getters.hpp"
38 #include "common/notifier.hpp"
39
40 namespace ot {
41 namespace MeshCoP {
42
CopyTo(char * aBuffer,uint8_t aMaxSize) const43 uint8_t NameData::CopyTo(char *aBuffer, uint8_t aMaxSize) const
44 {
45 MutableData<kWithUint8Length> destData;
46
47 destData.Init(aBuffer, aMaxSize);
48 destData.ClearBytes();
49 IgnoreError(destData.CopyBytesFrom(*this));
50
51 return destData.GetLength();
52 }
53
GetAsData(void) const54 NameData NetworkName::GetAsData(void) const
55 {
56 return NameData(m8, static_cast<uint8_t>(StringLength(m8, kMaxSize + 1)));
57 }
58
Set(const char * aNameString)59 Error NetworkName::Set(const char *aNameString)
60 {
61 // When setting `NetworkName` from a string, we treat it as `NameData`
62 // with `kMaxSize + 1` chars. `NetworkName::Set(data)` will look
63 // for null char in the data (within its given size) to calculate
64 // the name's length and ensure that the name fits in `kMaxSize`
65 // chars. The `+ 1` ensures that a `aNameString` with length
66 // longer than `kMaxSize` is correctly rejected (returning error
67 // `kErrorInvalidArgs`).
68 // Additionally, no minimum length is verified in order to ensure
69 // backwards compatibility with previous versions that allowed
70 // a zero-length name.
71
72 Error error;
73 NameData data(aNameString, kMaxSize + 1);
74
75 VerifyOrExit(IsValidUtf8String(aNameString), error = kErrorInvalidArgs);
76
77 error = Set(data);
78
79 exit:
80 return error;
81 }
82
Set(const NameData & aNameData)83 Error NetworkName::Set(const NameData &aNameData)
84 {
85 Error error = kErrorNone;
86 NameData data = aNameData;
87 uint8_t newLen = static_cast<uint8_t>(StringLength(data.GetBuffer(), data.GetLength()));
88
89 VerifyOrExit(newLen <= kMaxSize, error = kErrorInvalidArgs);
90
91 data.SetLength(newLen);
92
93 // Ensure the new name does not match the current one.
94 if (data.MatchesBytesIn(m8) && m8[newLen] == '\0')
95 {
96 ExitNow(error = kErrorAlready);
97 }
98
99 data.CopyBytesTo(m8);
100 m8[newLen] = '\0';
101
102 exit:
103 return error;
104 }
105
operator ==(const NetworkName & aOther) const106 bool NetworkName::operator==(const NetworkName &aOther) const { return GetAsData() == aOther.GetAsData(); }
107
NetworkNameManager(Instance & aInstance)108 NetworkNameManager::NetworkNameManager(Instance &aInstance)
109 : InstanceLocator(aInstance)
110 {
111 IgnoreError(SetNetworkName(NetworkName::kNetworkNameInit));
112
113 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
114 IgnoreError(SetDomainName(NetworkName::kDomainNameInit));
115 #endif
116 }
117
SetNetworkName(const char * aNameString)118 Error NetworkNameManager::SetNetworkName(const char *aNameString)
119 {
120 return SignalNetworkNameChange(mNetworkName.Set(aNameString));
121 }
122
SetNetworkName(const NameData & aNameData)123 Error NetworkNameManager::SetNetworkName(const NameData &aNameData)
124 {
125 return SignalNetworkNameChange(mNetworkName.Set(aNameData));
126 }
127
SignalNetworkNameChange(Error aError)128 Error NetworkNameManager::SignalNetworkNameChange(Error aError)
129 {
130 switch (aError)
131 {
132 case kErrorNone:
133 Get<Notifier>().Signal(kEventThreadNetworkNameChanged);
134 break;
135
136 case kErrorAlready:
137 Get<Notifier>().SignalIfFirst(kEventThreadNetworkNameChanged);
138 aError = kErrorNone;
139 break;
140
141 default:
142 break;
143 }
144
145 return aError;
146 }
147
148 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
SetDomainName(const char * aNameString)149 Error NetworkNameManager::SetDomainName(const char *aNameString)
150 {
151 Error error = mDomainName.Set(aNameString);
152
153 return (error == kErrorAlready) ? kErrorNone : error;
154 }
155
SetDomainName(const NameData & aNameData)156 Error NetworkNameManager::SetDomainName(const NameData &aNameData)
157 {
158 Error error = mDomainName.Set(aNameData);
159
160 return (error == kErrorAlready) ? kErrorNone : error;
161 }
162 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
163
164 } // namespace MeshCoP
165 } // namespace ot
166