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