diff -r 000000000000 -r af10295192d8 networkingtestandutils/ipv6to4tunnel/src/6to4_flow.cpp --- /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 +#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 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