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: // ip4_hdr.h - IPv4 header structure williamr@2: // Defines the basic classes for accessing the header williamr@2: // structures within IPv4 packets. williamr@2: // williamr@2: williamr@2: williamr@2: williamr@2: /** williamr@2: @file ip4_hdr.h williamr@2: @ingroup ip_packet_formats williamr@2: @publishedAll williamr@2: @released williamr@2: */ williamr@2: williamr@2: #ifndef __IP4_HDR_H__ williamr@2: #define __IP4_HDR_H__ williamr@2: williamr@2: #include "in_hdr.h" williamr@2: #include "es_sock.h" // for ByteOrder only!!! williamr@2: williamr@2: /** williamr@2: * @addtogroup ip_packet_formats williamr@2: * @{ williamr@2: */ williamr@2: williamr@2: /** williamr@2: * @name IP v4 constants williamr@2: * @since v7.0 williamr@2: * @publishedAll williamr@2: * @released williamr@2: */ williamr@4: //@{ williamr@4: const TUint8 KInet4IP_DF = 0x40; //< Don't Fragment flag williamr@4: const TUint8 KInet4IP_MF = 0x20; //< More Fragments flag williamr@4: const TInt KInetMinMtu = 68; //< Minimum MTU as defined in RFC-791 williamr@4: //@} williamr@2: williamr@2: class TInet6HeaderIP4 williamr@2: /** williamr@2: * Encapsulates an IPv4 IP header. williamr@2: * williamr@2: @verbatim williamr@2: ************************ williamr@2: Extract from the RFC-791 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: |Version| IHL |Type of Service| Total Length | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | Identification |Flags| Fragment Offset | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | Time to Live | Protocol | Header Checksum | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | Source Address | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | Destination Address | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: | Options | Padding | williamr@2: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ williamr@2: williamr@2: Version: 4 bits = 4 williamr@2: IHL: 4 bits williamr@2: williamr@2: Internet Header Length is the length of the internet header in 32 williamr@2: bit words, and thus points to the beginning of the data. Note that williamr@2: the minimum value for a correct header is 5 williamr@2: williamr@2: Type of Service: 8 bits williamr@2: Bits 0-2: Precedence. williamr@2: Bit 3: 0 = Normal Delay, 1 = Low Delay. williamr@2: Bits 4: 0 = Normal Throughput, 1 = High Throughput. williamr@2: Bits 5: 0 = Normal Relibility, 1 = High Relibility. williamr@2: Bit 6-7: Reserved for Future Use. williamr@2: williamr@2: Precedence williamr@2: williamr@2: 111 - Network Control williamr@2: 110 - Internetwork Control williamr@2: 101 - CRITIC/ECP williamr@2: 100 - Flash Override williamr@2: 011 - Flash williamr@2: 010 - Immediate williamr@2: 001 - Priority williamr@2: 000 - Routine williamr@2: Total Length: 16 bits williamr@2: Total Length is the length of the datagram, measured in octets, williamr@2: including internet header and data. williamr@2: williamr@2: Identification: 16 bits williamr@2: An identifying value assigned by the sender to aid in assembling the williamr@2: fragments of a datagram. williamr@2: williamr@2: Flags: 3 bits williamr@2: Various Control Flags. williamr@2: williamr@2: Bit 0: reserved, must be zero williamr@2: Bit 1: (DF) 0 = May Fragment, 1 = Don't Fragment. williamr@2: Bit 2: (MF) 0 = Last Fragment, 1 = More Fragments. williamr@2: williamr@2: Fragment Offset: 13 bits williamr@2: williamr@2: This field indicates where in the datagram this fragment belongs. williamr@2: The fragment offset is measured in units of 8 octets (64 bits). The williamr@2: first fragment has offset zero. williamr@2: williamr@2: Time to Live: 8 bits williamr@2: Protocol: 8 bits williamr@2: Header Checksum: 16 bits williamr@2: Source Address: 32 bits williamr@2: Destination Address: 32 bits williamr@2: @endverbatim williamr@2: williamr@2: @publishedAll williamr@2: @released williamr@2: @since v7.0 williamr@2: */ williamr@2: { williamr@2: public: williamr@2: // williamr@2: // Basic williamr@2: // williamr@2: /** williamr@2: * Gets the minimum header length. williamr@2: * @return Minimum header length (= 20) williamr@2: * @since v7.0 williamr@2: */ williamr@2: inline static TInt MinHeaderLength() {return 4*5; } williamr@2: /** williamr@2: * Gets the maximum header length. williamr@2: * @return Maximum header length (= 60) williamr@2: * @since v7.0 williamr@2: */ williamr@2: inline static TInt MaxHeaderLength() {return 4*15; } williamr@2: /** williamr@2: * Gets a pointer to the byte following the header. williamr@2: * @return Pointer to the byte following the header williamr@2: * @since v7.0 williamr@2: */ williamr@2: inline TUint8 *EndPtr() {return i + HeaderLength();} williamr@2: williamr@2: enum TOffsets williamr@2: { williamr@2: O_TotalLength = 2, williamr@2: O_FragmentOffset = 6, williamr@2: O_TTL = 8, williamr@2: O_Protocol = 9 williamr@2: }; williamr@2: inline TInt Version() const williamr@2: /** williamr@2: * Gets the IP version from the header. williamr@2: * @return IP version (should be 4 for IPv4) williamr@2: */ williamr@2: { williamr@2: return (i[0] >> 4) & 0xf; williamr@2: } williamr@2: inline TInt HeaderLength() const williamr@2: /** williamr@2: * Gets the header length. williamr@2: * @return Header length in bytes (based on IHL field) williamr@2: */ williamr@2: { williamr@2: return (i[0] & 0x0f) * 4; // Note: Returns bytes length! williamr@2: } williamr@2: inline TInt TOS() const williamr@2: /** williamr@2: * Gets the TOS from the header. williamr@2: * @return TOS williamr@2: */ williamr@2: { williamr@2: return i[1]; williamr@2: } williamr@2: inline TBool EcnIsCongestion() williamr@2: /** williamr@2: * Gets ECN congestion status. williamr@2: * williamr@2: * see RFC-3168 for details. williamr@2: * williamr@2: * @return True, if CE bit is set on an ECN capable packet. williamr@2: */ williamr@2: { williamr@2: return ((TOS() & 3) == 3); williamr@2: } williamr@2: inline TInt TotalLength() const williamr@2: /** williamr@2: * Gets the Total Length from the header. williamr@2: * @return Total Length (includes IP header and payload) williamr@2: */ williamr@2: { williamr@2: return (i[2] << 8) | i[3]; williamr@2: } williamr@2: inline TInt Identification() const williamr@2: /** williamr@2: * Gets the Identification from the header. williamr@2: * @return Identification [0..65535] williamr@2: */ williamr@2: { williamr@2: return (i[4] << 8) | i[5]; williamr@2: } williamr@2: inline TInt Flags() const williamr@2: /** williamr@2: * Gets the Flags from the header. williamr@2: * @note returns flags byte as is, may include bits of fragment offset! williamr@2: * @return Flags williamr@2: */ williamr@2: { williamr@2: return i[6]; williamr@2: } williamr@2: inline TInt DF() const williamr@2: /** williamr@2: * Gets the DF flag from the header. williamr@2: * @return DF flag (= KInet4IP_DF, if set and zero otherwise) williamr@2: */ williamr@2: { williamr@2: return i[6] & KInet4IP_DF; williamr@2: } williamr@2: inline TInt MF() const williamr@2: /** williamr@2: * Gets the MF flag from the header. williamr@2: * @return MF flag (= KInet4IP_MF, if set and zero otherwise) williamr@2: */ williamr@2: { williamr@2: return i[6] & KInet4IP_MF; williamr@2: } williamr@2: inline TInt FragmentOffset() const williamr@2: /** williamr@2: * Gets the Fragment Offset from the header. williamr@2: * @return Fragment Offset (raw 8 octet units, not a bytes offset!) williamr@2: */ williamr@2: { williamr@2: return ((i[6] & 0x1f) << 8) | i[7]; williamr@2: } williamr@2: inline TInt Ttl() const williamr@2: /** williamr@2: * Gets the Time to Live from the header. williamr@2: * @return Time to Live [0..255] williamr@2: */ williamr@2: { williamr@2: return i[8]; williamr@2: } williamr@2: inline TInt Protocol() const williamr@2: /** williamr@2: * Gets the Protocol from the header. williamr@2: * @return Protocol [0..255] williamr@2: */ williamr@2: { williamr@2: return i[9]; williamr@2: } williamr@2: inline TInt Checksum() const williamr@2: /** williamr@2: * Gets the Header Checksum from the header. williamr@2: * @return Header Checksum (in NETWORK byte order) williamr@2: */ williamr@2: { williamr@2: // Checksum is used in network byte order williamr@2: return *((TUint16 *)&i[10]); williamr@2: } williamr@2: inline TUint32 SrcAddr() const williamr@2: /** williamr@2: * Gets the source address from the header. williamr@2: * @return Source address (in host byte order) williamr@2: */ williamr@2: { williamr@2: return (i[12] << 24) | (i[13] << 16) | (i[14] << 8) | i[15]; williamr@2: } williamr@2: inline TUint32 DstAddr() const williamr@2: /** williamr@2: * Gets the destination address from the header. williamr@2: * @return Destination address (in host byte order) williamr@2: */ williamr@2: { williamr@2: return (i[16] << 24) | (i[17] << 16) | (i[18] << 8) | i[19]; williamr@2: } williamr@2: inline TUint32 &SrcAddrRef() const williamr@2: /** williamr@2: * Gets a raw reference to the source address in network byte order. williamr@2: * @return Raw reference to the source address williamr@2: */ williamr@2: { williamr@2: return (TUint32 &)i[12]; williamr@2: } williamr@2: inline TUint32 &DstAddrRef() const williamr@2: /** williamr@2: * Gets a raw reference to the destination address in network byte order. williamr@2: * @return Raw reference to the destination address williamr@2: */ williamr@2: { williamr@2: return (TUint32 &)i[16]; williamr@2: } williamr@2: inline TPtrC8 Options() const williamr@2: /** williamr@2: * Gets the Options from the header (const overload). williamr@2: * @return Options williamr@2: * williamr@2: * @note williamr@2: * This relies on correct value of IHL! Must not be used with williamr@2: * corrupt headers (will panic if IHL < 5!). williamr@2: */ williamr@2: { williamr@2: // *NOTE* This includes the padding bytes, or can be empty! williamr@2: return TPtrC8((TUint8 *)&i[20], HeaderLength() - 20); williamr@2: } williamr@2: inline TPtr8 Options() williamr@2: /** williamr@2: * Gets the Options from the header. williamr@2: * @return Options williamr@2: * williamr@2: * @note williamr@2: * This relies on correct value of IHL! Must not be used with williamr@2: * corrupt headers (will panic if IHL < 5!). williamr@2: */ williamr@2: { williamr@2: // It is yet unclear what will be the best way to build williamr@2: // the options into the header. For the time being this williamr@2: // method returns a modifiable Ptr8 to the the available williamr@2: // option space. For this to work, the application must williamr@2: // have used the SetHeaderLength() to fix the current williamr@2: // available length. williamr@2: return TPtr8((TUint8 *)&i[20], HeaderLength() - 20); williamr@2: } williamr@2: williamr@2: inline void Init(TInt aTOS = 0) williamr@2: /** williamr@2: * Initialises the IPv4 header to basic initial values. williamr@2: * williamr@2: * @li Version = 4 williamr@2: * @li IHL = 5 williamr@2: * @li Total Length = 20 williamr@2: * @li Identification = 0 williamr@2: * @li Fragment Offset = 0 williamr@2: * @li Flags = 0 williamr@2: * @li TTL = 0 williamr@2: * @li Checksum = 0 williamr@2: * @li TOS = aTOS (optional parameter, default = 0) williamr@2: * williamr@2: * However, address fields are not touched, because williamr@2: * they are most often set separately in any case. williamr@2: * williamr@2: * @param aTOS initial value for TOS (= 0) williamr@2: */ williamr@2: { williamr@2: i[0] = 0x45; // Version=4, IHL=5 (= 20 bytes) williamr@2: i[1] = (TUint8)aTOS; // TOS williamr@2: i[2] = 0; williamr@2: i[3] = 20; // Total length = 20 williamr@2: *((TInt32 *)&i[4]) = 0; // Identification = 0, flags=0, Fragment offset = 0; williamr@2: *((TInt32 *)&i[8]) = 0; // TTL=0,Protocol=0,Checksum=0 williamr@2: } williamr@2: // williamr@2: // Build, set IP header field values into the packet williamr@2: // williamr@2: williamr@2: inline void SetVersion(TInt aVersion) williamr@2: /** williamr@2: * Sets the IP version in the header. williamr@2: * @param aVersion the value to be set [0..15] williamr@2: */ williamr@2: { williamr@2: i[0] = (TUint8)((i[0] & 0x0f) | ((aVersion << 4) & 0xf0)); williamr@2: } williamr@2: inline void SetHeaderLength(TInt aLength) williamr@2: /** williamr@2: * Sets the header length (IHL). williamr@2: * williamr@2: * @param aLength williamr@2: * the length of the IPv4 header in BYTES. The williamr@2: * IHL is computed from this, without any sanity williamr@2: * checks. The valid range is [20..60]. williamr@2: */ williamr@2: { williamr@2: i[0] = (TUint8)((i[0] & 0xf0) | ((aLength >> 2) & 0x0f)); williamr@2: } williamr@2: inline void SetTOS(TInt aTos) williamr@2: /** williamr@2: * Sets the TOS in the header. williamr@2: * @param aTos The TOS value to set [0..255] williamr@2: */ williamr@2: { williamr@2: i[1] = (TUint8)aTos; williamr@2: } williamr@2: inline void SetTotalLength(TInt aLength) williamr@2: /** williamr@2: * Sets the Total Length in the header. williamr@2: * williamr@2: * @param aLength the length of combined header and williamr@2: * payload in bytes (no sanity checks, but the williamr@2: * value should be in range [20..65535]). Only williamr@2: * 16 least significant bits used. williamr@2: */ williamr@2: { williamr@2: i[3] = (TUint8)aLength; williamr@2: i[2] = (TUint8)(aLength >> 8); williamr@2: } williamr@2: inline void SetIdentification(TInt aId) williamr@2: /** williamr@2: * Sets the Identification in the header. williamr@2: * williamr@2: * @param aId the value to be set (only 16 least significant williamr@2: * bits are used, rest is ignored). williamr@2: */ williamr@2: { williamr@2: i[5] = (TUint8)aId; williamr@2: i[4] = (TUint8)(aId >> 8); williamr@2: } williamr@2: williamr@2: inline void SetFlags(TUint8 aFlags) williamr@2: /** williamr@2: * Sets the Flags in the header. williamr@2: * williamr@2: * Flags are assumed to be in the three most significant bits williamr@2: * of aFlags, in their proper positions. williamr@2: * (No individual settings provided, if you need to set a flag williamr@2: * without affecting others, use Flags() to get old values, williamr@2: * update and store the result with SetFlags()). williamr@2: * williamr@2: * @param aFlags contains the new flags williamr@2: */ williamr@2: { williamr@2: i[6] = (TUint8)((i[6] & 0x1f) | (aFlags & 0xe0)); williamr@2: } williamr@2: inline void SetFragmentOffset(TUint16 aOffset) williamr@2: /** williamr@2: * Sets the Fragment Offset in the header. williamr@2: * @param aOffset Fragment Offset (8 octet units, not in bytes) williamr@2: */ williamr@2: { williamr@2: i[6] = (TUint8)((i[6] & 0xe0) | ((aOffset >> 8) & 0x1f)); williamr@2: i[7] = (TUint8)aOffset; williamr@2: } williamr@2: inline void SetTtl(TInt aTTL) williamr@2: /** williamr@2: * Sets the Time to Live in the header. williamr@2: * @param aTTL Time to Live [0..255] williamr@2: */ williamr@2: { williamr@2: i[8] = (TUint8)aTTL; williamr@2: } williamr@2: inline void SetProtocol(TInt aProtocol) williamr@2: /** williamr@2: * Sets the Protocol in the header. williamr@2: * @param aProtocol Protocol [0..255] williamr@2: */ williamr@2: { williamr@2: i[9] = (TUint8)aProtocol; williamr@2: } williamr@2: inline void SetChecksum(TInt aSum) williamr@2: /** williamr@2: * Sets the Header Checksum in the header. williamr@2: * @param aSum Header Checksum [0..65535] williamr@2: * (16 least significant bits stored williamr@2: * as is (assumed to be in NETWORK byte order). williamr@2: */ williamr@2: { williamr@2: // Checksum is used in network byte order williamr@2: *((TUint16 *)&i[10]) = (TUint16)aSum; williamr@2: } williamr@2: williamr@2: inline void SetSrcAddr(TUint32 aAddr) williamr@2: /** williamr@2: * Sets the source address in the header. williamr@2: * @param aAddr Source address (IPv4, 32 bit integer in host byte order) williamr@2: */ williamr@2: { williamr@2: i[15] = (TUint8)aAddr; williamr@2: i[14] = (TUint8)(aAddr >> 8); williamr@2: i[13] = (TUint8)(aAddr >> 16); williamr@2: i[12] = (TUint8)(aAddr >> 24); williamr@2: } williamr@2: williamr@2: inline void SetDstAddr(TUint32 aAddr) williamr@2: /** williamr@2: * Sets the destination address in the header. williamr@2: * @param aAddr Destination IPv4 address (32 bit integer) in host byte order williamr@2: */ williamr@2: { williamr@2: i[19] = (TUint8)aAddr; williamr@2: i[18] = (TUint8)(aAddr >> 8); williamr@2: i[17] = (TUint8)(aAddr >> 16); williamr@2: i[16] = (TUint8)(aAddr >> 24); williamr@2: } williamr@2: williamr@2: // williamr@2: // The old IPv4 stack leaves IP header in packet when passing it upwards, williamr@2: // but this header is swapped into host order. As upper layers really don't williamr@2: // need this stuff much, only few "compatibility" methods is defined here williamr@2: // williamr@2: williamr@2: inline TInt HostHeaderLength() const williamr@2: { williamr@2: /** williamr@2: * Gets the Header Length from a header that is in Host byte order. williamr@2: * @return Header Length williamr@2: * williamr@2: * @deprecated There is no reason to use swapped headers williamr@2: */ williamr@2: return (i[3] & 0x0f) * 4; williamr@2: } williamr@2: inline TInt HostProtocol() const williamr@2: /** williamr@2: * Gets the Protocol from a header that is in Host byte order. williamr@2: * @return Protocol williamr@2: * @deprecated There is no reason to use swapped headers williamr@2: */ williamr@2: { williamr@2: return i[10]; williamr@2: } williamr@2: williamr@2: inline void Swap() williamr@2: /** williamr@2: * Swaps the byte order in the header. williamr@2: * @deprecated There is no reason to use swapped headers williamr@2: */ williamr@2: { williamr@2: *(TUint32 *)(&i[0]) = ByteOrder::Swap32(*(TUint32 *)(&i[0])); williamr@2: *(TUint32 *)(&i[4]) = ByteOrder::Swap32(*(TUint32 *)(&i[4])); williamr@2: *(TUint32 *)(&i[8]) = ByteOrder::Swap32(*(TUint32 *)(&i[8])); williamr@2: *(TUint32 *)(&i[12]) = ByteOrder::Swap32(*(TUint32 *)(&i[12])); williamr@2: *(TUint32 *)(&i[16]) = ByteOrder::Swap32(*(TUint32 *)(&i[16])); williamr@2: } williamr@2: williamr@2: private: williamr@2: union williamr@2: { williamr@4: TUint8 i[4*15]; //< This allocates maximum length (60 bytes) williamr@4: TUint32 iAlign; //< A dummy member to force the 4 byte alignment williamr@2: }; williamr@2: }; williamr@2: williamr@2: /** williamr@2: * @name IP v4 Option constants williamr@2: * @since v7.0 williamr@2: * @publishedAll williamr@2: * @released williamr@2: */ williamr@4: //@{ williamr@2: const TUint8 KInet4Option_End = 0x00; williamr@2: const TUint8 KInet4Option_Nop = 0x01; williamr@2: williamr@2: const TUint8 KInet4OptionFlag_Copy = 0x80; williamr@4: //@} williamr@2: williamr@2: // williamr@2: // ICMP v4 constants williamr@2: // ================= williamr@2: // williamr@2: /** williamr@2: * @name ICMP v4 constants williamr@2: * @since v7.0 williamr@2: * @publishedAll williamr@2: * @released williamr@2: */ williamr@4: //@{ williamr@2: /** Echo Reply. See TInet6HeaderICMP_Echo (IPv4 and IPv6 use the same format). */ williamr@2: const TUint8 KInet4ICMP_EchoReply = 0; williamr@2: const TUint8 KInet4ICMP_Unreachable = 3; williamr@2: const TUint8 KInet4ICMP_SourceQuench = 4; williamr@2: const TUint8 KInet4ICMP_Redirect = 5; williamr@2: /** Echo Request. See TInet6HeaderICMP_Echo (IPv4 and IPv6 use the same format). */ williamr@2: const TUint8 KInet4ICMP_Echo = 8; williamr@2: const TUint8 KInet4ICMP_TimeExceeded = 11; williamr@2: const TUint8 KInet4ICMP_ParameterProblem = 12; williamr@2: const TUint8 KInet4ICMP_TimeStamp = 13; williamr@2: const TUint8 KInet4ICMP_TimeStampReply = 14; williamr@4: //@} williamr@2: williamr@4: //@} williamr@2: #endif