networkingtestandutils/ipv6to4tunnel/src/6to4_flow.cpp
changeset 0 af10295192d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkingtestandutils/ipv6to4tunnel/src/6to4_flow.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,227 @@
+// 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 "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Name        : 6to4_flow.cpp
+// Part of     : 6to4 plugin / 6to4.prt
+// Implements 6to4 automatic and configured tunnels, see
+// RFC 3056 & RFC 2893
+// Version     : 0.2
+//
+
+
+
+
+// INCLUDE FILES
+#include <in_chk.h>
+#include "6to4_flow.h"
+
+// EXTERNAL DATA STRUCTURES
+// EXTERNAL FUNCTION PROTOTYPES  
+// CONSTANTS
+// MACROS
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+// LOCAL FUNCTION PROTOTYPES
+// FORWARD DECLARATIONS
+
+// ============================= LOCAL FUNCTIONS ==============================
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+
+// ----------------------------------------------------------------------------
+// C6to4FlowInfo::C6to4FlowInfo
+// ----------------------------------------------------------------------------
+C6to4FlowInfo::C6to4FlowInfo(const TPacketHead &aHead)
+	: iInterfaceIndex(aHead.iInterfaceIndex)
+	{
+	// Need to save the inner selector information which is
+	// restored at ReadyL.
+	iSrcPort = aHead.iSrcPort;
+	iDstPort = aHead.iDstPort;
+	iIcmpType = aHead.iIcmpType;
+	iIcmpCode = aHead.iIcmpCode;
+	iInnerIp = aHead.ip6;
+	iDstId = aHead.iDstId;
+	iSrcId = aHead.iSrcId;
+	}
+	
+// ----------------------------------------------------------------------------
+// C6to4FlowInfo::~C6to4FlowInfo
+// ----------------------------------------------------------------------------
+C6to4FlowInfo::~C6to4FlowInfo ()
+	{
+	iPacket.Free();
+	}
+
+// ----------------------------------------------------------------------------
+// 6to4FlowInfo::ReadyL
+// The stack asks if the flow is ready to send. In the same time, the plugin
+// configures the source IP address from the flow, including configuring it to
+// the virtual interface. Set the packet source and destination IP addresses
+// for the inner (IPv6) header. Set the packet interface index. Set the packet 
+// next header to be the inner header next header and set the packet IP version
+// to 6.
+// ----------------------------------------------------------------------------
+//
+TInt C6to4FlowInfo::ReadyL (TPacketHead & aHead)
+	{
+	// Save the fixed packet content from the TPacketHead
+	iOffset = aHead.iOffset;
+	iPacket.Free();
+	if (iOffset > 0)
+		{
+		iPacket.Assign(aHead.iPacket);
+		aHead.iOffset = 0;
+		}
+
+	// Save the outer IP information
+	iOuterIp = aHead.ip6;
+
+	// Set inner header source and dest addresses
+	aHead.ip6 = iInnerIp;
+	// Inner Version() is not yet set correctly, make it correct.
+	aHead.ip6.SetVersion(iInnerIp.DstAddr().IsV4Mapped() ? 4 : 6);
+	aHead.iSrcId = iSrcId;
+	aHead.iDstId = iDstId;
+	aHead.iInterfaceIndex = iInterfaceIndex;
+	// Both next header and iProtocol must have the same value
+	// as the iPacket is now empty.
+	aHead.iProtocol = (TUint8)iInnerIp.NextHeader();
+	aHead.iSrcPort = iSrcPort;
+	aHead.iDstPort = iDstPort;
+	aHead.iIcmpType = iIcmpType;
+	aHead.iIcmpCode = iIcmpCode;
+	return EFlow_READY;
+	}
+
+// ----------------------------------------------------------------------------
+// 6to4FlowInfo::ApplyL
+// Final stage where the 6to4 touches the outgoing packet. Space is made for
+// the IP header and the IP header is initialized.
+// ----------------------------------------------------------------------------
+TInt C6to4FlowInfo::ApplyL (RMBufSendPacket & aPacket, RMBufSendInfo & aInfo)
+	{
+	// Apply the tunnelling
+
+	// Prepend the fixed content (if any) below the IP header
+	if (iOffset > 0)
+		{
+		RMBufChain work;
+		// Note: assumed that if CopyL leaves, then work is empty
+		iPacket.CopyL(work);
+		aPacket.Prepend(work);
+		aInfo.iLength += iOffset;
+		}
+	switch(iOuterIp.Version())
+		{
+		case 6:
+			{
+			aPacket.PrependL(sizeof(TInet6HeaderIP));
+			aInfo.iLength += sizeof(TInet6HeaderIP);
+			aInfo.iProtocol = KProtocolInet6Ip;
+
+			TInet6Packet<TInet6HeaderIP> ip(aPacket);
+			if (ip.iHdr == NULL)
+				User::Leave(KErrGeneral);
+
+			// Build outer IPv6 header (already in iOuterIp, just copy)
+			*ip.iHdr = iOuterIp;
+			// Note: Certain packets must not have ECN ECT bits set. tcp_sap.cpp sets
+			// KIpNoEcnEct for those packets.
+			if (aInfo.iFlags & KIpNoEcnEct)
+				{
+				ip.iHdr->SetTrafficClass(ip.iHdr->TrafficClass() & 0xfc);
+				}
+			ip.iHdr->SetPayloadLength(aInfo.iLength);
+			break;
+			}
+		case 4:
+			{
+			// Make space for IPv4 header
+			aPacket.PrependL (20);
+			aInfo.iLength += 20;
+			aInfo.iProtocol = KProtocolInetIp;
+
+			TInet6Checksum < TInet6HeaderIP4 > ip (aPacket);
+			if (ip.iHdr == NULL)
+				User::Leave (KErrGeneral);
+
+			// Build the outer IPv4 header
+			ip.iHdr->Init(iOuterIp.TrafficClass() & ((aInfo.iFlags & KIpNoEcnEct) ? 0xfc : 0xff));
+			// Raw Address load. Someone else must have already checked that
+			// both src and dst are IPv4 mapped addresses at the end of the
+			// ReadyL phase! This just does a blind copy.
+			ip.iHdr->DstAddrRef() = iOuterIp.DstAddr().u.iAddr32[3];
+			ip.iHdr->SrcAddrRef() = iOuterIp.SrcAddr().u.iAddr32[3];
+
+			// Somewhat ad hoc thing: if DontFragment flag is set, then
+			// set the DF bit to the IPv4 header...
+			if (aInfo.iFlags & KIpDontFragment)
+				ip.iHdr->SetFlags((TUint8)(ip.iHdr->Flags() | KInet4IP_DF));
+	
+			ip.iHdr->SetHeaderLength (20);
+			ip.iHdr->SetTotalLength (aInfo.iLength);
+			ip.iHdr->SetTtl(iOuterIp.HopLimit());
+
+			// NOTE!!! Something might be done for this. Now it is theoretically
+			// possible that a same host receives protocol 41 packets from us and
+			// we have two or more flows with protocol 41 AND two packets get 
+			// fragmented and are reassembled in the same time by the remote host
+			// AND the IPv4 identifier happens to be the same. That would break the
+			// reassembly process, but since this is practically "impossible", it is
+			// left now without a fix.
+			ip.iHdr->SetIdentification (iPacketID++);                                                                
+			ip.iHdr->SetProtocol (iOuterIp.NextHeader());
+
+			// Checksum of the outer header.
+			ip.ComputeChecksum ();
+			break;
+			}
+		default:
+			User::Leave(KErrGeneral);
+		}
+
+	// Pass the packet
+	return 0;
+	}
+
+// ----------------------------------------------------------------------------
+// 6to4FlowInfo::Open
+// Open the flow, keep reference count.
+// ----------------------------------------------------------------------------
+//
+
+void C6to4FlowInfo::Open ()
+	{
+	iRefs++;
+	}
+
+// ----------------------------------------------------------------------------
+// 6to4FlowInfo::Close
+// Close the flow if the reference count has reached zero. Remove the flow 
+// from any list it is stored.
+// ----------------------------------------------------------------------------
+//
+void C6to4FlowInfo::Close ()
+	{
+	if (--iRefs < 0)
+		{
+		delete this;
+		}
+	}
+
+// ========================== OTHER EXPORTED FUNCTIONS ========================
+
+//  End of File