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