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