williamr@2: // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). williamr@2: // All rights reserved. williamr@2: // This component and the accompanying materials are made available williamr@4: // under the terms of "Eclipse Public License v1.0" williamr@2: // which accompanies this distribution, and is available williamr@4: // at the URL "http://www.eclipse.org/legal/epl-v10.html". williamr@2: // williamr@2: // Initial Contributors: williamr@2: // Nokia Corporation - initial contribution. williamr@2: // williamr@2: // Contributors: williamr@2: // williamr@2: // Description: williamr@2: // in_chk.h - IPv6/IPv4 checksum module williamr@2: // Raw Internet Checksum computation from RMBufChain. williamr@2: // williamr@2: williamr@2: williamr@2: williamr@2: /** williamr@2: @file in_chk.h williamr@2: @publishedAll williamr@2: @released williamr@2: */ williamr@2: williamr@2: #ifndef __IN_CHK_H__ williamr@2: #define __IN_CHK_H__ williamr@2: williamr@2: #include "in_pkt.h" williamr@4: class RMBufChain; williamr@4: class RMBufPktInfo; williamr@2: williamr@2: /** Checksum calculation. williamr@2: williamr@2: @publishedAll williamr@2: @released williamr@2: */ williamr@2: class TChecksum { williamr@2: public: williamr@2: // TChecksum can be initialized with an old inverted checksum williamr@4: TChecksum(TUint16 aSum = ~0) : iSum((TUint16)~aSum) {} williamr@2: inline void Init(TUint16 aSum = ~0); williamr@2: williamr@2: inline TUint32 Sum(); williamr@2: inline TUint32 Sum32(); williamr@2: inline void Fold(); williamr@2: inline void Reverse(); williamr@2: williamr@2: // Complex Add methods williamr@2: IMPORT_C void Add(RMBufChain &aPacket, TInt aOffset); williamr@2: IMPORT_C void Add(RMBufChain &aPacket, const RMBufPktInfo *aInfo, TInt aOffset); williamr@2: williamr@2: // Inline Add methods williamr@2: inline void Add(const TUint16 *aPtr, TInt aLength); williamr@2: inline void AddHi(TUint8 aByte); williamr@2: inline void AddLo(TUint8 aByte); williamr@2: inline void Add(TUint16 aHalfWord); williamr@2: inline void Add(TUint32 aWord); williamr@2: inline void AddH(TUint16 aHalfWord); williamr@2: inline void AddH(TUint32 aWord); williamr@2: williamr@2: // Static methods williamr@2: static inline TUint32 Fold(TUint32 aSum); williamr@2: static inline TUint16 ComplementedFold(TUint32 aSum); williamr@2: IMPORT_C static TUint32 Calculate(const TUint16 *aPtr, TInt aLength); williamr@2: williamr@2: private: williamr@2: TUint32 iSum; // 32-bit sum in network byte order williamr@2: }; williamr@2: williamr@2: williamr@2: /** williamr@2: // TInet6Checksum Template. williamr@2: // williamr@2: // This template class provides utilitlies to compute and check williamr@2: // IPv6 Upper Layer Checksums williamr@2: // These are not merged with the TInet6Packet class, because that williamr@2: // class is intended (and is used) for all headers, not just upper williamr@2: // layers. williamr@2: // williamr@2: // The template parameter (Header class) must williamr@2: // - have Checksum() method williamr@2: // - have SetChecksum() method williamr@2: // - the checkum in header must be aligned to 16 bit word williamr@2: // williamr@2: // @publishedAll williamr@2: // @released williamr@2: */ williamr@2: template williamr@2: class TInet6Checksum : public TInet6Packet williamr@2: { williamr@2: public: williamr@2: TInet6Checksum() {} williamr@2: TInet6Checksum(RMBufChain &aPacket) : TInet6Packet(aPacket) {} williamr@2: TInet6Checksum(RMBufChain &aPacket, TInt aOffset) : TInet6Packet(aPacket, aOffset) {} williamr@2: void ComputeChecksum(RMBufChain &aPacket, const RMBufPktInfo *aInfo, TInt aOffset = 0); williamr@2: TBool VerifyChecksum(RMBufChain &aPacket, const RMBufPktInfo *aInfo, TInt aOffset = 0); williamr@2: void ComputeChecksum(); williamr@2: TBool VerifyChecksum(); williamr@2: }; williamr@2: williamr@2: // williamr@2: // Inline methods for TChecksum williamr@2: // williamr@2: williamr@2: inline void TChecksum::Init(TUint16 aSum) williamr@2: { williamr@2: iSum = ~aSum & 0xffff; williamr@2: } williamr@2: williamr@2: inline void TChecksum::Add(const TUint16 *aPtr, TInt aLength) williamr@2: { williamr@2: iSum += Calculate(aPtr, aLength); williamr@2: } williamr@2: williamr@2: inline void TChecksum::AddHi(TUint8 aByte) williamr@2: { williamr@2: iSum += (aByte << 8); williamr@2: } williamr@2: williamr@2: inline void TChecksum::AddLo(TUint8 aByte) williamr@2: { williamr@2: iSum += aByte; williamr@2: } williamr@2: williamr@2: // Add halfword in network byte order williamr@2: inline void TChecksum::Add(TUint16 aHalfWord) williamr@2: { williamr@2: iSum += aHalfWord; williamr@2: } williamr@2: williamr@2: // Add word in network byte order williamr@2: inline void TChecksum::Add(TUint32 aWord) williamr@2: { williamr@2: iSum += aWord >> 16; williamr@2: iSum += aWord & 0xffff; williamr@2: } williamr@2: williamr@2: // Add halfword in host byte order williamr@2: inline void TChecksum::AddH(TUint16 aHalfWord) williamr@2: { williamr@2: __DEBUG_ONLY (const TInt one = 1;) williamr@2: ASSERT(*(TUint8*)&one); //check that we are little-endian williamr@2: williamr@2: iSum += ((aHalfWord << 8) | (aHalfWord >> 8)) & 0xffff; williamr@2: } williamr@2: williamr@2: // Add word in host byte order williamr@2: inline void TChecksum::AddH(TUint32 aWord) williamr@2: { williamr@2: __DEBUG_ONLY (const TInt one = 1;) williamr@2: ASSERT(*(TUint8*)&one); //check that we are little-endian williamr@2: williamr@2: iSum += (aWord >> 24); // add octet 3 williamr@2: iSum += (aWord >> 8) & 0xffff, // add octets 2-1 williamr@2: iSum += (aWord << 8) & 0xff00; // add octet 0 williamr@2: } williamr@2: williamr@2: // Fold 32-bit sum into 16 bits williamr@2: inline void TChecksum::Fold() williamr@2: { williamr@2: iSum = Fold(iSum); williamr@2: } williamr@2: williamr@2: // Return 16-bit inverted checksum williamr@2: inline TUint32 TChecksum::Sum() williamr@2: { williamr@2: return Fold(iSum) ^ 0xffff; williamr@2: } williamr@2: williamr@2: // Return 32-bit intermediate sum williamr@2: inline TUint32 TChecksum::Sum32() williamr@2: { williamr@2: return iSum; williamr@2: } williamr@2: williamr@2: // Reverse checksum direction. Can be used to back out partial sums. williamr@2: inline void TChecksum::Reverse() williamr@2: { williamr@2: iSum = Sum(); williamr@2: } williamr@2: williamr@2: inline TUint32 TChecksum::Fold(TUint32 aSum) williamr@2: { williamr@2: aSum = (aSum >> 16) + (aSum & 0xffff); // Max: 0x0001fffe williamr@2: aSum += (aSum >> 16); // Max: 0x0001ffff williamr@2: return aSum & 0xffff; // Truncate to 16 bits williamr@2: } williamr@2: williamr@2: inline TUint16 TChecksum::ComplementedFold(TUint32 aSum) williamr@2: { williamr@2: return (TUint16)~Fold(aSum); williamr@2: } williamr@2: williamr@2: template williamr@2: void TInet6Checksum::ComputeChecksum(RMBufChain &aPacket, const RMBufPktInfo *aInfo, TInt aOffset) williamr@2: { williamr@2: TChecksum sum; williamr@2: this->iHdr->SetChecksum(0); williamr@2: sum.Add(aPacket, aInfo, aOffset); williamr@2: this->iHdr->SetChecksum(sum.Sum()); williamr@2: } williamr@2: williamr@2: template williamr@2: TBool TInet6Checksum::VerifyChecksum(RMBufChain &aPacket, const RMBufPktInfo *aInfo, TInt aOffset) williamr@2: { williamr@2: TChecksum sum; williamr@2: sum.Add(aPacket, aInfo, aOffset); williamr@2: return !sum.Sum(); williamr@2: } williamr@2: // williamr@2: // The following are mainly for the IPv4 Header checksum williamr@2: // williamr@2: template williamr@2: void TInet6Checksum::ComputeChecksum() williamr@2: { williamr@2: TChecksum sum; williamr@2: this->iHdr->SetChecksum(0); williamr@2: sum.Add((TUint16 *)(this->iHdr), this->iHdr->HeaderLength()); williamr@2: this->iHdr->SetChecksum(sum.Sum()); williamr@2: } williamr@2: williamr@2: template williamr@2: TBool TInet6Checksum::VerifyChecksum() williamr@2: { williamr@2: TChecksum sum; williamr@2: sum.Add((TUint16*)(this->iHdr), this->iHdr->HeaderLength()); williamr@2: return !sum.Sum(); williamr@2: } williamr@2: williamr@2: #endif