otError Frame::ValidatePsdu(void) const { otError error = OT_ERROR_NONE; uint8_t offset = FindPayloadIndex(); VerifyOrExit(offset != kInvalidIndex, error = OT_ERROR_PARSE); VerifyOrExit((offset + GetFooterLength()) <= GetPsduLength(), error = OT_ERROR_PARSE); exit: return error; }
ThreadError Frame::ValidatePsdu(void) { ThreadError error = kThreadError_Parse; uint8_t offset = 0; uint16_t fcf; uint8_t footerLength = kFcsSize; VerifyOrExit((offset += kFcfSize + kDsnSize) <= GetPsduLength(),); fcf = static_cast<uint16_t>((GetPsdu()[1] << 8) | GetPsdu()[0]); // Destinatinon PAN + Address switch (fcf & Frame::kFcfDstAddrMask) { case Frame::kFcfDstAddrNone: break; case Frame::kFcfDstAddrShort: offset += sizeof(PanId) + sizeof(ShortAddress); break; case Frame::kFcfDstAddrExt: offset += sizeof(PanId) + sizeof(ExtAddress); break; default: goto exit; } // Source PAN + Address switch (fcf & Frame::kFcfSrcAddrMask) { case Frame::kFcfSrcAddrNone: break; case Frame::kFcfSrcAddrShort: if ((fcf & Frame::kFcfPanidCompression) == 0) { offset += sizeof(PanId); } offset += sizeof(ShortAddress); break; case Frame::kFcfSrcAddrExt: if ((fcf & Frame::kFcfPanidCompression) == 0) { offset += sizeof(PanId); } offset += sizeof(ExtAddress); break; default: goto exit; } // Security Header if (fcf & Frame::kFcfSecurityEnabled) { VerifyOrExit(offset <= GetPsduLength(),); uint8_t secControl = GetPsdu()[offset]; switch (secControl & kKeyIdModeMask) { case kKeyIdMode0: offset += kKeySourceSizeMode0; break; case kKeyIdMode1: offset += kKeySourceSizeMode1 + kKeyIndexSize; break; case kKeyIdMode2: offset += kKeySourceSizeMode2 + kKeyIndexSize; break; case kKeyIdMode3: offset += kKeySourceSizeMode3 + kKeyIndexSize; break; } switch (secControl & kSecLevelMask) { case kSecNone: case kSecEnc: footerLength += kMic0Size; break; case kSecMic32: case kSecEncMic32: footerLength += kMic32Size; break; case kSecMic64: case kSecEncMic64: footerLength += kMic64Size; break; case kSecMic128: case kSecEncMic128: footerLength += kMic128Size; break; } }
const uint8_t *Frame::GetFooter(void) const { return GetPsdu() + GetPsduLength() - GetFooterLength(); }
uint8_t Frame::FindPayloadIndex(void) const { uint8_t index = 0; uint16_t fcf; // Frame Control index += kFcfSize; // Sequence Number index += kDsnSize; VerifyOrExit((index + kFcsSize) <= GetPsduLength(), index = kInvalidIndex); fcf = GetFrameControlField(); // Destination PAN + Address switch (fcf & kFcfDstAddrMask) { case kFcfDstAddrNone: break; case kFcfDstAddrShort: index += sizeof(PanId) + sizeof(ShortAddress); break; case kFcfDstAddrExt: index += sizeof(PanId) + sizeof(ExtAddress); break; default: ExitNow(index = kInvalidIndex); } // Source PAN + Address switch (fcf & kFcfSrcAddrMask) { case kFcfSrcAddrNone: break; case kFcfSrcAddrShort: if ((fcf & kFcfPanidCompression) == 0) { index += sizeof(PanId); } index += sizeof(ShortAddress); break; case kFcfSrcAddrExt: if ((fcf & kFcfPanidCompression) == 0) { index += sizeof(PanId); } index += sizeof(ExtAddress); break; default: ExitNow(index = kInvalidIndex); } VerifyOrExit((index + kFcsSize) <= GetPsduLength(), index = kInvalidIndex); // Security Control + Frame Counter + Key Identifier if ((fcf & kFcfSecurityEnabled) != 0) { uint8_t securityControl = *(GetPsdu() + index); index += kSecurityControlSize + kFrameCounterSize; switch (securityControl & kKeyIdModeMask) { case kKeyIdMode0: index += kKeySourceSizeMode0; break; case kKeyIdMode1: index += kKeySourceSizeMode1 + kKeyIndexSize; break; case kKeyIdMode2: index += kKeySourceSizeMode2 + kKeyIndexSize; break; case kKeyIdMode3: index += kKeySourceSizeMode3 + kKeyIndexSize; break; } } // Command ID if ((fcf & kFcfFrameTypeMask) == kFcfFrameMacCmd) { index += kCommandIdSize; } exit: return index; }
uint8_t Frame::GetPayloadLength(void) const { return GetPsduLength() - (GetHeaderLength() + GetFooterLength()); }