• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 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 #include "mac_frame.h"
30 
31 #include <assert.h>
32 
33 #include <openthread/platform/radio.h>
34 
35 #include "common/code_utils.hpp"
36 #include "mac/mac_frame.hpp"
37 
38 using namespace ot;
39 
otMacFrameDoesAddrMatch(const otRadioFrame * aFrame,otPanId aPanId,otShortAddress aShortAddress,const otExtAddress * aExtAddress)40 bool otMacFrameDoesAddrMatch(const otRadioFrame *aFrame,
41                              otPanId             aPanId,
42                              otShortAddress      aShortAddress,
43                              const otExtAddress *aExtAddress)
44 {
45     return otMacFrameDoesAddrMatchAny(aFrame, aPanId, aShortAddress, Mac::kShortAddrInvalid, aExtAddress);
46 }
47 
otMacFrameDoesAddrMatchAny(const otRadioFrame * aFrame,otPanId aPanId,otShortAddress aShortAddress,otShortAddress aAltShortAddress,const otExtAddress * aExtAddress)48 bool otMacFrameDoesAddrMatchAny(const otRadioFrame *aFrame,
49                                 otPanId             aPanId,
50                                 otShortAddress      aShortAddress,
51                                 otShortAddress      aAltShortAddress,
52                                 const otExtAddress *aExtAddress)
53 {
54     const Mac::Frame &frame = *static_cast<const Mac::Frame *>(aFrame);
55     bool              rval  = true;
56     Mac::Address      dst;
57     Mac::PanId        panid;
58 
59     VerifyOrExit(frame.GetDstAddr(dst) == kErrorNone, rval = false);
60 
61     switch (dst.GetType())
62     {
63     case Mac::Address::kTypeShort:
64         VerifyOrExit(dst.GetShort() == Mac::kShortAddrBroadcast || dst.GetShort() == aShortAddress ||
65                          (aAltShortAddress != Mac::kShortAddrInvalid && dst.GetShort() == aAltShortAddress),
66                      rval = false);
67         break;
68 
69     case Mac::Address::kTypeExtended:
70         VerifyOrExit(dst.GetExtended() == *static_cast<const Mac::ExtAddress *>(aExtAddress), rval = false);
71         break;
72 
73     case Mac::Address::kTypeNone:
74         break;
75     }
76 
77     SuccessOrExit(frame.GetDstPanId(panid));
78     VerifyOrExit(panid == Mac::kPanIdBroadcast || panid == aPanId, rval = false);
79 
80 exit:
81     return rval;
82 }
83 
otMacFrameIsAck(const otRadioFrame * aFrame)84 bool otMacFrameIsAck(const otRadioFrame *aFrame)
85 {
86     return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kTypeAck;
87 }
88 
otMacFrameIsData(const otRadioFrame * aFrame)89 bool otMacFrameIsData(const otRadioFrame *aFrame)
90 {
91     return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kTypeData;
92 }
93 
otMacFrameIsCommand(const otRadioFrame * aFrame)94 bool otMacFrameIsCommand(const otRadioFrame *aFrame)
95 {
96     return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kTypeMacCmd;
97 }
98 
otMacFrameIsDataRequest(const otRadioFrame * aFrame)99 bool otMacFrameIsDataRequest(const otRadioFrame *aFrame)
100 {
101     return static_cast<const Mac::Frame *>(aFrame)->IsDataRequestCommand();
102 }
103 
otMacFrameIsAckRequested(const otRadioFrame * aFrame)104 bool otMacFrameIsAckRequested(const otRadioFrame *aFrame)
105 {
106     return static_cast<const Mac::Frame *>(aFrame)->GetAckRequest();
107 }
108 
GetOtMacAddress(const Mac::Address & aInAddress,otMacAddress * aOutAddress)109 static void GetOtMacAddress(const Mac::Address &aInAddress, otMacAddress *aOutAddress)
110 {
111     switch (aInAddress.GetType())
112     {
113     case Mac::Address::kTypeNone:
114         aOutAddress->mType = OT_MAC_ADDRESS_TYPE_NONE;
115         break;
116 
117     case Mac::Address::kTypeShort:
118         aOutAddress->mType                  = OT_MAC_ADDRESS_TYPE_SHORT;
119         aOutAddress->mAddress.mShortAddress = aInAddress.GetShort();
120         break;
121 
122     case Mac::Address::kTypeExtended:
123         aOutAddress->mType                = OT_MAC_ADDRESS_TYPE_EXTENDED;
124         aOutAddress->mAddress.mExtAddress = aInAddress.GetExtended();
125         break;
126     }
127 }
128 
otMacFrameGetSrcAddr(const otRadioFrame * aFrame,otMacAddress * aMacAddress)129 otError otMacFrameGetSrcAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress)
130 {
131     otError      error;
132     Mac::Address address;
133 
134     error = static_cast<const Mac::Frame *>(aFrame)->GetSrcAddr(address);
135     SuccessOrExit(error);
136 
137     GetOtMacAddress(address, aMacAddress);
138 
139 exit:
140     return error;
141 }
142 
otMacFrameGetDstAddr(const otRadioFrame * aFrame,otMacAddress * aMacAddress)143 otError otMacFrameGetDstAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress)
144 {
145     otError      error;
146     Mac::Address address;
147 
148     error = static_cast<const Mac::Frame *>(aFrame)->GetDstAddr(address);
149     SuccessOrExit(error);
150 
151     GetOtMacAddress(address, aMacAddress);
152 
153 exit:
154     return error;
155 }
156 
otMacFrameGetSequence(const otRadioFrame * aFrame,uint8_t * aSequence)157 otError otMacFrameGetSequence(const otRadioFrame *aFrame, uint8_t *aSequence)
158 {
159     otError error;
160 
161     if (static_cast<const Mac::Frame *>(aFrame)->IsSequencePresent())
162     {
163         *aSequence = static_cast<const Mac::Frame *>(aFrame)->GetSequence();
164         error      = kErrorNone;
165     }
166     else
167     {
168         error = kErrorParse;
169     }
170 
171     return error;
172 }
173 
otMacFrameProcessTransmitAesCcm(otRadioFrame * aFrame,const otExtAddress * aExtAddress)174 void otMacFrameProcessTransmitAesCcm(otRadioFrame *aFrame, const otExtAddress *aExtAddress)
175 {
176     static_cast<Mac::TxFrame *>(aFrame)->ProcessTransmitAesCcm(*static_cast<const Mac::ExtAddress *>(aExtAddress));
177 }
178 
otMacFrameIsVersion2015(const otRadioFrame * aFrame)179 bool otMacFrameIsVersion2015(const otRadioFrame *aFrame)
180 {
181     return static_cast<const Mac::Frame *>(aFrame)->IsVersion2015();
182 }
183 
otMacFrameGenerateImmAck(const otRadioFrame * aFrame,bool aIsFramePending,otRadioFrame * aAckFrame)184 void otMacFrameGenerateImmAck(const otRadioFrame *aFrame, bool aIsFramePending, otRadioFrame *aAckFrame)
185 {
186     assert(aFrame != nullptr && aAckFrame != nullptr);
187 
188     static_cast<Mac::TxFrame *>(aAckFrame)->GenerateImmAck(*static_cast<const Mac::RxFrame *>(aFrame), aIsFramePending);
189 }
190 
191 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
otMacFrameGenerateEnhAck(const otRadioFrame * aFrame,bool aIsFramePending,const uint8_t * aIeData,uint8_t aIeLength,otRadioFrame * aAckFrame)192 otError otMacFrameGenerateEnhAck(const otRadioFrame *aFrame,
193                                  bool                aIsFramePending,
194                                  const uint8_t      *aIeData,
195                                  uint8_t             aIeLength,
196                                  otRadioFrame       *aAckFrame)
197 {
198     assert(aFrame != nullptr && aAckFrame != nullptr);
199 
200     return static_cast<Mac::TxFrame *>(aAckFrame)->GenerateEnhAck(*static_cast<const Mac::RxFrame *>(aFrame),
201                                                                   aIsFramePending, aIeData, aIeLength);
202 }
203 #endif
204 
205 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
otMacFrameSetCslIe(otRadioFrame * aFrame,uint16_t aCslPeriod,uint16_t aCslPhase)206 void otMacFrameSetCslIe(otRadioFrame *aFrame, uint16_t aCslPeriod, uint16_t aCslPhase)
207 {
208     static_cast<Mac::Frame *>(aFrame)->SetCslIe(aCslPeriod, aCslPhase);
209 }
210 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
211 
otMacFrameIsSecurityEnabled(otRadioFrame * aFrame)212 bool otMacFrameIsSecurityEnabled(otRadioFrame *aFrame)
213 {
214     return static_cast<const Mac::Frame *>(aFrame)->GetSecurityEnabled();
215 }
216 
otMacFrameIsKeyIdMode1(otRadioFrame * aFrame)217 bool otMacFrameIsKeyIdMode1(otRadioFrame *aFrame)
218 {
219     uint8_t keyIdMode;
220     otError error;
221 
222     error = static_cast<const Mac::Frame *>(aFrame)->GetKeyIdMode(keyIdMode);
223 
224     return (error == OT_ERROR_NONE) ? (keyIdMode == Mac::Frame::kKeyIdMode1) : false;
225 }
226 
otMacFrameIsKeyIdMode2(otRadioFrame * aFrame)227 bool otMacFrameIsKeyIdMode2(otRadioFrame *aFrame)
228 {
229     uint8_t keyIdMode;
230     otError error;
231 
232     error = static_cast<const Mac::Frame *>(aFrame)->GetKeyIdMode(keyIdMode);
233 
234     return (error == OT_ERROR_NONE) ? (keyIdMode == Mac::Frame::kKeyIdMode2) : false;
235 }
236 
otMacFrameGetKeyId(otRadioFrame * aFrame)237 uint8_t otMacFrameGetKeyId(otRadioFrame *aFrame)
238 {
239     uint8_t keyId = 0;
240 
241     IgnoreError(static_cast<const Mac::Frame *>(aFrame)->GetKeyId(keyId));
242 
243     return keyId;
244 }
245 
otMacFrameSetKeyId(otRadioFrame * aFrame,uint8_t aKeyId)246 void otMacFrameSetKeyId(otRadioFrame *aFrame, uint8_t aKeyId) { static_cast<Mac::Frame *>(aFrame)->SetKeyId(aKeyId); }
247 
otMacFrameGetFrameCounter(otRadioFrame * aFrame)248 uint32_t otMacFrameGetFrameCounter(otRadioFrame *aFrame)
249 {
250     uint32_t frameCounter = UINT32_MAX;
251 
252     IgnoreError(static_cast<Mac::Frame *>(aFrame)->GetFrameCounter(frameCounter));
253 
254     return frameCounter;
255 }
256 
otMacFrameSetFrameCounter(otRadioFrame * aFrame,uint32_t aFrameCounter)257 void otMacFrameSetFrameCounter(otRadioFrame *aFrame, uint32_t aFrameCounter)
258 {
259     static_cast<Mac::Frame *>(aFrame)->SetFrameCounter(aFrameCounter);
260 }
261 
262 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
otMacFrameGenerateCslIeTemplate(uint8_t * aDest)263 uint8_t otMacFrameGenerateCslIeTemplate(uint8_t *aDest)
264 {
265     assert(aDest != nullptr);
266 
267     reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::CslIe::kHeaderIeId);
268     reinterpret_cast<Mac::HeaderIe *>(aDest)->SetLength(sizeof(Mac::CslIe));
269 
270     return sizeof(Mac::HeaderIe) + sizeof(Mac::CslIe);
271 }
272 #endif
273 
274 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
otMacFrameGenerateEnhAckProbingIe(uint8_t * aDest,const uint8_t * aIeData,uint8_t aIeDataLength)275 uint8_t otMacFrameGenerateEnhAckProbingIe(uint8_t *aDest, const uint8_t *aIeData, uint8_t aIeDataLength)
276 {
277     uint8_t len = sizeof(Mac::VendorIeHeader) + aIeDataLength;
278 
279     assert(aDest != nullptr);
280 
281     reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::ThreadIe::kHeaderIeId);
282     reinterpret_cast<Mac::HeaderIe *>(aDest)->SetLength(len);
283 
284     aDest += sizeof(Mac::HeaderIe);
285 
286     reinterpret_cast<Mac::VendorIeHeader *>(aDest)->SetVendorOui(Mac::ThreadIe::kVendorOuiThreadCompanyId);
287     reinterpret_cast<Mac::VendorIeHeader *>(aDest)->SetSubType(Mac::ThreadIe::kEnhAckProbingIe);
288 
289     if (aIeData != nullptr)
290     {
291         aDest += sizeof(Mac::VendorIeHeader);
292         memcpy(aDest, aIeData, aIeDataLength);
293     }
294 
295     return sizeof(Mac::HeaderIe) + len;
296 }
297 
otMacFrameSetEnhAckProbingIe(otRadioFrame * aFrame,const uint8_t * aData,uint8_t aDataLen)298 void otMacFrameSetEnhAckProbingIe(otRadioFrame *aFrame, const uint8_t *aData, uint8_t aDataLen)
299 {
300     assert(aFrame != nullptr && aData != nullptr);
301 
302     reinterpret_cast<Mac::Frame *>(aFrame)->SetEnhAckProbingIe(aData, aDataLen);
303 }
304 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
305 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
ComputeCslPhase(uint32_t aRadioTime,otRadioContext * aRadioContext)306 static uint16_t ComputeCslPhase(uint32_t aRadioTime, otRadioContext *aRadioContext)
307 {
308     return (aRadioContext->mCslSampleTime - aRadioTime) % (aRadioContext->mCslPeriod * OT_US_PER_TEN_SYMBOLS) /
309            OT_US_PER_TEN_SYMBOLS;
310 }
311 #endif
otMacFrameProcessTransmitSecurity(otRadioFrame * aFrame,otRadioContext * aRadioContext)312 otError otMacFrameProcessTransmitSecurity(otRadioFrame *aFrame, otRadioContext *aRadioContext)
313 {
314     otError error = OT_ERROR_NONE;
315 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
316     otMacKeyMaterial *key = nullptr;
317     uint8_t           keyId;
318     uint32_t          frameCounter;
319     bool              processKeyId;
320 
321     processKeyId =
322 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
323         otMacFrameIsKeyIdMode2(aFrame) ||
324 #endif
325         otMacFrameIsKeyIdMode1(aFrame);
326 
327     VerifyOrExit(otMacFrameIsSecurityEnabled(aFrame) && processKeyId && !aFrame->mInfo.mTxInfo.mIsSecurityProcessed);
328 
329     if (otMacFrameIsAck(aFrame))
330     {
331         keyId = otMacFrameGetKeyId(aFrame);
332 
333         VerifyOrExit(keyId != 0, error = OT_ERROR_FAILED);
334 
335         if (keyId == aRadioContext->mKeyId)
336         {
337             key          = &aRadioContext->mCurrKey;
338             frameCounter = aRadioContext->mMacFrameCounter++;
339         }
340         else if (keyId == aRadioContext->mKeyId - 1)
341         {
342             key          = &aRadioContext->mPrevKey;
343             frameCounter = aRadioContext->mPrevMacFrameCounter++;
344         }
345         else if (keyId == aRadioContext->mKeyId + 1)
346         {
347             key          = &aRadioContext->mNextKey;
348             frameCounter = 0;
349         }
350         else
351         {
352             ExitNow(error = OT_ERROR_SECURITY);
353         }
354     }
355     else if (!aFrame->mInfo.mTxInfo.mIsHeaderUpdated)
356     {
357         key          = &aRadioContext->mCurrKey;
358         keyId        = aRadioContext->mKeyId;
359         frameCounter = aRadioContext->mMacFrameCounter++;
360     }
361 
362     if (key != nullptr)
363     {
364         aFrame->mInfo.mTxInfo.mAesKey = key;
365 
366         otMacFrameSetKeyId(aFrame, keyId);
367         otMacFrameSetFrameCounter(aFrame, frameCounter);
368         aFrame->mInfo.mTxInfo.mIsHeaderUpdated = true;
369     }
370 #else
371     VerifyOrExit(!aFrame->mInfo.mTxInfo.mIsSecurityProcessed);
372 #endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
373 
374     otMacFrameProcessTransmitAesCcm(aFrame, &aRadioContext->mExtAddress);
375 
376 exit:
377     return error;
378 }
379 
380 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
otMacFrameUpdateTimeIe(otRadioFrame * aFrame,uint64_t aRadioTime,otRadioContext * aRadioContext)381 void otMacFrameUpdateTimeIe(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioContext *aRadioContext)
382 {
383     uint8_t *timeIe;
384     uint64_t time;
385 
386     VerifyOrExit((aFrame->mInfo.mTxInfo.mIeInfo != nullptr) && (aFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0));
387 
388     timeIe  = aFrame->mPsdu + aFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset;
389     time    = aRadioTime + aFrame->mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset;
390     *timeIe = aFrame->mInfo.mTxInfo.mIeInfo->mTimeSyncSeq;
391 
392     *(++timeIe) = static_cast<uint8_t>(time & 0xff);
393     for (uint8_t i = 1; i < sizeof(uint64_t); i++)
394     {
395         time        = time >> 8;
396         *(++timeIe) = static_cast<uint8_t>(time & 0xff);
397     }
398 
399 exit:
400     return;
401 }
402 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
403 
otMacFrameProcessTxSfd(otRadioFrame * aFrame,uint64_t aRadioTime,otRadioContext * aRadioContext)404 otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioContext *aRadioContext)
405 {
406 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
407     if (aRadioContext->mCslPeriod > 0) // CSL IE should be filled for every transmit attempt
408     {
409         otMacFrameSetCslIe(aFrame, aRadioContext->mCslPeriod, ComputeCslPhase(aRadioTime, aRadioContext));
410     }
411 #endif
412 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
413     otMacFrameUpdateTimeIe(aFrame, aRadioTime, aRadioContext);
414 #endif
415     aFrame->mInfo.mTxInfo.mTimestamp = aRadioTime;
416     return otMacFrameProcessTransmitSecurity(aFrame, aRadioContext);
417 }
418