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: // tcp_hdr.h - TCP protocol header structure williamr@2: // Defines the basic classes for accessing the header structures within TCP packets. williamr@2: // williamr@2: williamr@2: williamr@2: williamr@2: /** williamr@2: @file tcp_hdr.h williamr@2: @ingroup ip_packet_formats williamr@2: @publishedAll williamr@2: @released williamr@2: */ williamr@2: williamr@2: #ifndef __TCP_HDR_H__ williamr@2: #define __TCP_HDR_H__ williamr@2: williamr@2: #include williamr@2: #include "in_hdr.h" williamr@2: #include "sbque.h" williamr@2: williamr@2: /** williamr@2: * @addtogroup ip_packet_formats williamr@2: * @{ williamr@2: */ williamr@2: williamr@2: // williamr@2: // TInet6HeaderTCP williamr@2: // williamr@2: // *NOTE* williamr@2: // TInet6HeaderTCP declares for maximum length TCP header williamr@2: // (64 bytes). A valid TCP packet can be shorter and failing williamr@2: // to map full 64 bytes from a packet is not an error condition. williamr@2: // williamr@2: williamr@2: /** @name TCP Header length constants williamr@2: * @{ williamr@2: */ williamr@2: const TInt KTcpMinHeaderLength = 20; williamr@2: const TInt KTcpMaxHeaderLength = 60; williamr@2: const TInt KTcpMaxOptionLength = 40; williamr@2: /** @} */ williamr@2: williamr@2: /** @name TCP control flags williamr@2: * @{ williamr@2: */ williamr@2: const TUint8 KTcpCtlFIN = 1; williamr@2: const TUint8 KTcpCtlSYN = 2; williamr@2: const TUint8 KTcpCtlRST = 4; williamr@2: const TUint8 KTcpCtlPSH = 8; williamr@2: const TUint8 KTcpCtlACK = 16; williamr@2: const TUint8 KTcpCtlURG = 32; williamr@2: const TUint8 KTcpCtlECE = 0x40; williamr@2: const TUint8 KTcpCtlCWR = 0x80; williamr@2: /** @} */ williamr@2: williamr@2: /** @name TCP options williamr@2: * @{ williamr@2: */ williamr@2: const TUint8 KTcpOptEnd = 0; williamr@2: const TUint8 KTcpOptNop = 1; williamr@2: const TUint8 KTcpOptMSS = 2; williamr@2: const TUint8 KTcpOptWScale = 3; williamr@2: const TUint8 KTcpOptSackOk = 4; williamr@2: const TUint8 KTcpOptSack = 5; williamr@2: const TUint8 KTcpOptTimeStamps = 8; williamr@2: const TUint8 KTcpOptCount = 9; williamr@2: williamr@2: const TUint8 KTcpOptMinLen[] = {1, 1, 4, 3, 2, 6, 2, 2, 10}; williamr@2: const TUint8 KTcpOptMaxLen[] = {1, 1, 4, 3, 2, 36, 40, 40, 10}; williamr@2: const TUint32 KTcpOptAlignFlag = 0x00000001; williamr@2: /** @} */ williamr@2: williamr@2: williamr@2: class TTcpOptions williamr@2: /** TCP Options Header. williamr@2: @publishedAll williamr@2: @released williamr@2: */ williamr@2: { williamr@2: public: williamr@2: inline TTcpOptions() { Init(); } williamr@2: IMPORT_C void Init(); williamr@2: IMPORT_C TInt Length() const; williamr@2: inline TBool Error() const { return iError; } williamr@2: inline void ClearError() { iError = EFalse; } williamr@2: williamr@2: inline TInt MSS() const { return iMSS; } williamr@2: inline void SetMSS(TInt aMSS) { iMSS = aMSS; } williamr@2: inline void ClearMSS() { iMSS = -1; } williamr@2: williamr@2: inline TBool TimeStamps() const { return iTimeStamps; } williamr@2: inline TBool TimeStamps(TUint32& aTsVal, TUint32& aTsEcr) const williamr@2: { williamr@2: aTsVal = iTsVal; williamr@2: aTsEcr = iTsEcr; williamr@2: return iTimeStamps; williamr@2: } williamr@2: inline void SetTimeStamps(TUint32 aTsVal, TUint32 aTsEcr) williamr@2: { williamr@2: iTsVal = aTsVal; williamr@2: iTsEcr = aTsEcr; williamr@2: iTimeStamps = ETrue; williamr@2: } williamr@2: inline void ClearTimeStamps() { iTimeStamps = EFalse; } williamr@2: williamr@2: inline TBool SackOk() const { return iSackOk; } williamr@2: inline void SetSackOk() { iSackOk = ETrue; } williamr@2: inline void ClearSackOk() { iSackOk = EFalse; } williamr@2: inline void SuppressSack(TBool aBool=ETrue) { iSuppressSack = aBool; } williamr@2: inline SequenceBlockQueue& SackBlocks() { return iBlocks; } williamr@2: williamr@2: inline TInt Unknown() const { return iUnknown; } williamr@2: inline void ClearUnknown() { iUnknown = 0; } williamr@2: williamr@4: // Query window scale option from TCP header options. williamr@4: // Wscale == 1 means scale factor 1, i.e. shift count of 0 is used in TCP option. williamr@4: // Wscale == 0 means that wscale option is not used in TCP header. williamr@2: inline TUint WindowScale() const { return iWscale; } williamr@2: williamr@2: inline void SetWindowScale(TUint8 aWscale) { iWscale = aWscale; } williamr@2: williamr@2: /** williamr@2: If set, each option will be aligned to 32-bit longword boundaries with Nop padding. williamr@2: By default the Nop padding is not applied. williamr@2: williamr@2: @param aAlignNop ETrue if option alignment should be applied. williamr@2: */ williamr@2: inline void SetAlignOpt(TBool aAlignOpt) williamr@2: { williamr@2: if(aAlignOpt) williamr@2: iFlags |= KTcpOptAlignFlag; williamr@2: else williamr@2: iFlags &= ~KTcpOptAlignFlag; williamr@2: } williamr@2: williamr@2: private: williamr@2: friend class TInet6HeaderTCP; williamr@2: williamr@2: IMPORT_C TBool ProcessOptions(const TUint8 *aPtr, TUint aLen); williamr@2: IMPORT_C TUint OutputOptions(TUint8 *aPtr, TUint aMaxLen); williamr@2: williamr@2: void CheckOptAlignment(TUint8* aPtr, TUint& aI, TUint aNumBytes); williamr@2: williamr@2: inline TInt AlignedLength(TInt aLength) const williamr@2: /** williamr@2: Calculate the actual space requirement for option with given length. williamr@2: williamr@2: Takes optional 32-bit alignment into account. williamr@2: */ williamr@2: { if (iFlags & KTcpOptAlignFlag) return (aLength + 3) & ~3; else return aLength; } williamr@2: williamr@2: TInt iMSS; williamr@2: TInt iUnknown; williamr@2: TUint32 iTsVal; williamr@2: TUint32 iTsEcr; williamr@2: SequenceBlockQueue iBlocks; williamr@2: TBool iError; williamr@2: TBool iTimeStamps; williamr@2: TBool iSackOk; williamr@2: TBool iSuppressSack; williamr@4: TUint iWscale; //< Window scale option [RFC 1323]. williamr@4: TUint32 iFlags; //< ETrue if options are to be aligned. williamr@2: }; williamr@2: williamr@2: williamr@2: williamr@2: class TInet6HeaderTCP williamr@2: /** TCP segment header. williamr@2: @verbatim williamr@2: Extract from RFC-793 williamr@2: williamr@2: 0 1 2 3 williamr@2: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | Source Port | Destination Port | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | Sequence Number | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | Acknowledgment Number | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | Data | |U|A|P|R|S|F| | williamr@2: | Offset| Reserved |R|C|S|S|Y|I| Window | williamr@2: | | |G|K|H|T|N|N| | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | Checksum | Urgent Pointer | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | Options | Padding | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | data | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: @endverbatim williamr@2: @publishedAll williamr@2: @released williamr@2: */ williamr@2: { williamr@2: public: williamr@2: // williamr@2: // Basic williamr@2: // williamr@2: inline static TInt MinHeaderLength() {return KTcpMinHeaderLength; } williamr@2: inline static TInt MaxHeaderLength() {return KTcpMaxHeaderLength; } williamr@2: inline TUint8 *EndPtr() {return i + HeaderLength();} williamr@2: // williamr@2: // Access, Get TCP field values from the packet williamr@2: // williamr@2: inline TUint SrcPort() const williamr@2: { williamr@2: return (i[0] << 8) + i[1]; williamr@2: } williamr@2: inline TUint DstPort() const williamr@2: { williamr@2: return (i[2] << 8) + i[3]; williamr@2: } williamr@2: inline TTcpSeqNum Sequence() const williamr@2: { williamr@2: return (i[4] << 24) | (i[5] << 16) | (i[6] << 8) | i[7]; williamr@2: } williamr@2: inline TTcpSeqNum Acknowledgment() const williamr@2: { williamr@2: return (i[8] << 24) | (i[9] << 16) | (i[10] << 8) | i[11]; williamr@2: } williamr@2: inline TInt HeaderLength() const williamr@2: { williamr@2: // Return TCP Header Length in bytes (including options and padding) williamr@2: return (i[12] >> 2) & (0xF << 2); williamr@2: } williamr@2: // williamr@2: // A testing method for each individual Control Bit is provided williamr@2: // (It remains to be seen whether this is useful or not). Note williamr@2: // also that the result of the AND is returned, not 0 and 1. williamr@2: // williamr@2: inline TInt FIN() const williamr@2: { williamr@2: return i[13] & KTcpCtlFIN; williamr@2: } williamr@2: inline TInt SYN() const williamr@2: { williamr@2: return i[13] & KTcpCtlSYN; williamr@2: } williamr@2: inline TInt RST() const williamr@2: { williamr@2: return i[13] & KTcpCtlRST; williamr@2: } williamr@2: inline TInt PSH() const williamr@2: { williamr@2: return i[13] & KTcpCtlPSH; williamr@2: } williamr@2: inline TInt ACK() const williamr@2: { williamr@2: return i[13] & KTcpCtlACK; williamr@2: } williamr@2: inline TInt URG() const williamr@2: { williamr@2: return i[13] & KTcpCtlURG; williamr@2: } williamr@2: williamr@4: // ECN Echo flag [RFC 3168]. williamr@2: inline TInt ECE() const williamr@2: { williamr@2: return i[13] & KTcpCtlECE; williamr@2: } williamr@2: williamr@4: // ECN: Congestion Window Reduced [RFC 3168]. williamr@2: inline TInt CWR() const williamr@2: { williamr@2: return i[13] & KTcpCtlCWR; williamr@2: } williamr@2: williamr@2: // A method to access all of the above as is. Note that this williamr@2: // also returns the reserved unspecified bits. Value can be williamr@2: // non-zero, even if none of the above is set. However, it only williamr@2: // returns unspecified bits from the 13th byte, not any from 12th! williamr@2: inline TUint8 Control() const williamr@2: { williamr@2: return i[13]; williamr@2: } williamr@2: // williamr@2: inline TUint Window() const williamr@2: { williamr@2: return (i[14] << 8) + i[15]; williamr@2: } williamr@2: inline TUint Checksum() const williamr@2: { williamr@2: // Checksum is used in network byte order williamr@2: return *((TUint16 *)&i[16]); williamr@2: } williamr@2: inline TUint Urgent() const williamr@2: { williamr@2: return (i[18] << 8) + i[19]; williamr@2: } williamr@2: inline TBool Options(TTcpOptions& aOptions) const williamr@2: { williamr@2: return aOptions.ProcessOptions(i + KTcpMinHeaderLength, HeaderLength() - KTcpMinHeaderLength); williamr@2: } williamr@2: //Backwards compatibility, mainly for IPRotor. williamr@2: inline TPtr8 Options() const williamr@2: { williamr@2: TInt len = HeaderLength() - 20; williamr@2: return TPtr8((TUint8 *)&i[20], len, len); williamr@2: } williamr@2: williamr@2: // williamr@2: // Build, Set TCP field value to the packet williamr@2: // williamr@2: inline void SetSrcPort(TUint aPort) williamr@2: { williamr@2: i[0] = (TUint8)(aPort >> 8); williamr@2: i[1] = (TUint8)aPort; williamr@2: } williamr@2: inline void SetDstPort(TUint aPort) williamr@2: { williamr@2: i[2] = (TUint8)(aPort >> 8); williamr@2: i[3] = (TUint8)aPort; williamr@2: } williamr@2: inline void SetSequence(TTcpSeqNum aSeq) williamr@2: { williamr@2: i[7] = (TUint8)aSeq.Uint32(); williamr@2: i[6] = (TUint8)(aSeq.Uint32() >> 8); williamr@2: i[5] = (TUint8)(aSeq.Uint32() >> 16); williamr@2: i[4] = (TUint8)(aSeq.Uint32() >> 24); williamr@2: } williamr@2: inline void SetAcknowledgment(TTcpSeqNum aAck) williamr@2: { williamr@2: i[11] = (TUint8)aAck.Uint32(); williamr@2: i[10] = (TUint8)(aAck.Uint32() >> 8); williamr@2: i[9] = (TUint8)(aAck.Uint32() >> 16); williamr@2: i[8] = (TUint8)(aAck.Uint32() >> 24); williamr@2: } williamr@2: inline void SetHeaderLength(TUint aLength) williamr@2: { williamr@2: // *NOTE* A very low level function, no sanity williamr@2: // checks on value, no rounding up. Value is just williamr@2: // truncated and shifted to the proper position williamr@2: // (all other bits of this byte should always williamr@2: // be zero!) williamr@2: i[12] = (TUint8)((aLength >> 2) <<4); williamr@2: } williamr@2: // williamr@2: // A set method for each individual Control Bit is provided williamr@2: // (It remains to be seen whether this is sensible or not). williamr@2: // williamr@2: inline void SetFIN() williamr@2: { williamr@2: i[13] |= KTcpCtlFIN; williamr@2: } williamr@2: inline void SetSYN() williamr@2: { williamr@2: i[13] |= KTcpCtlSYN; williamr@2: } williamr@2: inline void SetRST() williamr@2: { williamr@2: i[13] |= KTcpCtlRST; williamr@2: } williamr@2: inline void SetPSH() williamr@2: { williamr@2: i[13] |= KTcpCtlPSH; williamr@2: } williamr@2: inline void SetACK() williamr@2: { williamr@2: i[13] |= KTcpCtlACK; williamr@2: } williamr@2: inline void SetURG() williamr@2: { williamr@2: i[13] |= KTcpCtlURG; williamr@2: } williamr@2: williamr@4: // Set ECN Echo flag [RFC 3168]. williamr@2: inline void SetECE() williamr@2: { williamr@2: i[13] |= KTcpCtlECE; williamr@2: } williamr@2: williamr@4: // Set ECN Congestion Window Reduced [RFC 3168]. williamr@2: inline void SetCWR() williamr@2: { williamr@2: i[13] |= KTcpCtlCWR; williamr@2: } williamr@2: williamr@2: // williamr@2: // Note: does not touch the unused control bits at 12th byte!!! williamr@2: // williamr@2: inline void SetControl(TUint8 aFlags) williamr@2: { williamr@2: i[13] = aFlags; williamr@2: } williamr@2: // williamr@2: inline void SetWindow(TUint aWin) williamr@2: { williamr@2: i[15] = (TUint8)aWin; williamr@2: i[14] = (TUint8)(aWin >> 8); williamr@2: } williamr@2: inline void SetChecksum(TUint aSum) williamr@2: { williamr@2: // Checksum is used in network byte order williamr@2: *((TUint16 *)&i[16]) = (TUint16)aSum; williamr@2: } williamr@2: inline void SetUrgent(TUint aOff) williamr@2: { williamr@2: i[19] = (TUint8)aOff; williamr@2: i[18] = (TUint8)(aOff >> 8); williamr@2: } williamr@2: inline TInt SetOptions(TTcpOptions& aOptions) williamr@2: { williamr@2: TInt optLen = aOptions.OutputOptions(i + KTcpMinHeaderLength, KTcpMaxOptionLength); williamr@2: SetHeaderLength(KTcpMinHeaderLength + optLen); williamr@2: return optLen; williamr@2: } williamr@2: williamr@2: protected: williamr@2: TUint8 i[KTcpMaxHeaderLength]; williamr@2: }; williamr@2: williamr@2: /** @} */ williamr@2: #endif