1 /*
2  *  Copyright (c) 2016-2019, 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 MAC types such as Address, Extended PAN Identifier, Network Name, etc.
32  */
33 
34 #include "mac_types.hpp"
35 
36 #include <stdio.h>
37 
38 #include "common/code_utils.hpp"
39 #include "common/random.hpp"
40 #include "common/string.hpp"
41 
42 namespace ot {
43 namespace Mac {
44 
GenerateRandomPanId(void)45 PanId GenerateRandomPanId(void)
46 {
47     PanId panId;
48 
49     do
50     {
51         panId = Random::NonCrypto::GetUint16();
52     } while (panId == kPanIdBroadcast);
53 
54     return panId;
55 }
56 
57 #if !OPENTHREAD_RADIO
GenerateRandom(void)58 void ExtAddress::GenerateRandom(void)
59 {
60     IgnoreError(Random::Crypto::FillBuffer(m8, sizeof(ExtAddress)));
61     SetGroup(false);
62     SetLocal(true);
63 }
64 #endif
65 
ToString(void) const66 ExtAddress::InfoString ExtAddress::ToString(void) const
67 {
68     InfoString string;
69 
70     string.AppendHexBytes(m8, sizeof(ExtAddress));
71 
72     return string;
73 }
74 
CopyAddress(uint8_t * aDst,const uint8_t * aSrc,CopyByteOrder aByteOrder)75 void ExtAddress::CopyAddress(uint8_t *aDst, const uint8_t *aSrc, CopyByteOrder aByteOrder)
76 {
77     switch (aByteOrder)
78     {
79     case kNormalByteOrder:
80         memcpy(aDst, aSrc, sizeof(ExtAddress));
81         break;
82 
83     case kReverseByteOrder:
84         aSrc += sizeof(ExtAddress) - 1;
85         for (uint8_t len = sizeof(ExtAddress); len > 0; len--)
86         {
87             *aDst++ = *aSrc--;
88         }
89         break;
90     }
91 }
92 
ToString(void) const93 Address::InfoString Address::ToString(void) const
94 {
95     InfoString string;
96 
97     if (mType == kTypeExtended)
98     {
99         string.AppendHexBytes(GetExtended().m8, sizeof(ExtAddress));
100     }
101     else if (mType == kTypeNone)
102     {
103         string.Append("None");
104     }
105     else
106     {
107         string.Append("0x%04x", GetShort());
108     }
109 
110     return string;
111 }
112 
ToString(void) const113 ExtendedPanId::InfoString ExtendedPanId::ToString(void) const
114 {
115     InfoString string;
116 
117     string.AppendHexBytes(m8, sizeof(ExtendedPanId));
118 
119     return string;
120 }
121 
CopyTo(char * aBuffer,uint8_t aMaxSize) const122 uint8_t NameData::CopyTo(char *aBuffer, uint8_t aMaxSize) const
123 {
124     uint8_t len = GetLength();
125 
126     memset(aBuffer, 0, aMaxSize);
127 
128     if (len > aMaxSize)
129     {
130         len = aMaxSize;
131     }
132 
133     memcpy(aBuffer, GetBuffer(), len);
134 
135     return len;
136 }
137 
GetAsData(void) const138 NameData NetworkName::GetAsData(void) const
139 {
140     uint8_t len = static_cast<uint8_t>(StringLength(m8, kMaxSize + 1));
141 
142     return NameData(m8, len);
143 }
144 
Set(const char * aNameString)145 Error NetworkName::Set(const char *aNameString)
146 {
147     // When setting `NetworkName` from a string, we treat it as `NameData`
148     // with `kMaxSize + 1` chars. `NetworkName::Set(data)` will look
149     // for null char in the data (within its given size) to calculate
150     // the name's length and ensure that the name fits in `kMaxSize`
151     // chars. The `+ 1` ensures that a `aNameString` with length
152     // longer than `kMaxSize` is correctly rejected (returning error
153     // `kErrorInvalidArgs`).
154 
155     Error    error;
156     NameData data(aNameString, kMaxSize + 1);
157 
158     VerifyOrExit(IsValidUtf8String(aNameString), error = kErrorInvalidArgs);
159 
160     error = Set(data);
161 
162 exit:
163     return error;
164 }
165 
Set(const NameData & aNameData)166 Error NetworkName::Set(const NameData &aNameData)
167 {
168     Error   error  = kErrorNone;
169     uint8_t newLen = static_cast<uint8_t>(StringLength(aNameData.GetBuffer(), aNameData.GetLength()));
170 
171     VerifyOrExit(newLen <= kMaxSize, error = kErrorInvalidArgs);
172 
173     // Ensure the new name does not match the current one.
174     VerifyOrExit(memcmp(m8, aNameData.GetBuffer(), newLen) || (m8[newLen] != '\0'), error = kErrorAlready);
175 
176     memcpy(m8, aNameData.GetBuffer(), newLen);
177     m8[newLen] = '\0';
178 
179 exit:
180     return error;
181 }
182 
operator ==(const NetworkName & aOther) const183 bool NetworkName::operator==(const NetworkName &aOther) const
184 {
185     NameData data      = GetAsData();
186     NameData otherData = aOther.GetAsData();
187 
188     return (data.GetLength() == otherData.GetLength()) &&
189            (memcmp(data.GetBuffer(), otherData.GetBuffer(), data.GetLength()) == 0);
190 }
191 
192 #if OPENTHREAD_CONFIG_MULTI_RADIO
193 
194 const RadioType RadioTypes::kAllRadioTypes[kNumRadioTypes] = {
195 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
196     kRadioTypeIeee802154,
197 #endif
198 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
199     kRadioTypeTrel,
200 #endif
201 };
202 
AddAll(void)203 void RadioTypes::AddAll(void)
204 {
205 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
206     Add(kRadioTypeIeee802154);
207 #endif
208 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
209     Add(kRadioTypeTrel);
210 #endif
211 }
212 
ToString(void) const213 RadioTypes::InfoString RadioTypes::ToString(void) const
214 {
215     InfoString string;
216     bool       addComma = false;
217 
218     string.Append("{");
219 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
220     if (Contains(kRadioTypeIeee802154))
221     {
222         string.Append("%s%s", addComma ? ", " : " ", RadioTypeToString(kRadioTypeIeee802154));
223         addComma = true;
224     }
225 #endif
226 
227 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
228     if (Contains(kRadioTypeTrel))
229     {
230         string.Append("%s%s", addComma ? ", " : " ", RadioTypeToString(kRadioTypeTrel));
231         addComma = true;
232     }
233 #endif
234 
235     OT_UNUSED_VARIABLE(addComma);
236 
237     string.Append(" }");
238 
239     return string;
240 }
241 
RadioTypeToString(RadioType aRadioType)242 const char *RadioTypeToString(RadioType aRadioType)
243 {
244     const char *str = "unknown";
245 
246     switch (aRadioType)
247     {
248 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
249     case kRadioTypeIeee802154:
250         str = "15.4";
251         break;
252 #endif
253 
254 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
255     case kRadioTypeTrel:
256         str = "trel";
257         break;
258 #endif
259     }
260 
261     return str;
262 }
263 
Get(RadioType aRadioType) const264 uint32_t LinkFrameCounters::Get(RadioType aRadioType) const
265 {
266     uint32_t counter = 0;
267 
268     switch (aRadioType)
269     {
270 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
271     case kRadioTypeIeee802154:
272         counter = m154Counter;
273         break;
274 #endif
275 
276 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
277     case kRadioTypeTrel:
278         counter = mTrelCounter;
279         break;
280 #endif
281     }
282 
283     return counter;
284 }
285 
Set(RadioType aRadioType,uint32_t aCounter)286 void LinkFrameCounters::Set(RadioType aRadioType, uint32_t aCounter)
287 {
288     switch (aRadioType)
289     {
290 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
291     case kRadioTypeIeee802154:
292         m154Counter = aCounter;
293         break;
294 #endif
295 
296 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
297     case kRadioTypeTrel:
298         mTrelCounter = aCounter;
299         break;
300 #endif
301     }
302 }
303 
304 #endif // OPENTHREAD_CONFIG_MULTI_RADIO
305 
GetMaximum(void) const306 uint32_t LinkFrameCounters::GetMaximum(void) const
307 {
308     uint32_t counter = 0;
309 
310 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
311     if (counter < m154Counter)
312     {
313         counter = m154Counter;
314     }
315 #endif
316 
317 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
318     if (counter < mTrelCounter)
319     {
320         counter = mTrelCounter;
321     }
322 #endif
323 
324     return counter;
325 }
326 
SetAll(uint32_t aCounter)327 void LinkFrameCounters::SetAll(uint32_t aCounter)
328 {
329 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
330     m154Counter = aCounter;
331 #endif
332 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
333     mTrelCounter = aCounter;
334 #endif
335 }
336 
337 } // namespace Mac
338 } // namespace ot
339