networkingtestandutils/ipv6to4tunnel/src/6to4_flow.cpp
changeset 0 af10295192d8
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Name        : 6to4_flow.cpp
       
    15 // Part of     : 6to4 plugin / 6to4.prt
       
    16 // Implements 6to4 automatic and configured tunnels, see
       
    17 // RFC 3056 & RFC 2893
       
    18 // Version     : 0.2
       
    19 //
       
    20 
       
    21 
       
    22 
       
    23 
       
    24 // INCLUDE FILES
       
    25 #include <in_chk.h>
       
    26 #include "6to4_flow.h"
       
    27 
       
    28 // EXTERNAL DATA STRUCTURES
       
    29 // EXTERNAL FUNCTION PROTOTYPES  
       
    30 // CONSTANTS
       
    31 // MACROS
       
    32 // LOCAL CONSTANTS AND MACROS
       
    33 
       
    34 // MODULE DATA STRUCTURES
       
    35 // LOCAL FUNCTION PROTOTYPES
       
    36 // FORWARD DECLARATIONS
       
    37 
       
    38 // ============================= LOCAL FUNCTIONS ==============================
       
    39 
       
    40 // ============================ MEMBER FUNCTIONS ==============================
       
    41 
       
    42 
       
    43 // ----------------------------------------------------------------------------
       
    44 // C6to4FlowInfo::C6to4FlowInfo
       
    45 // ----------------------------------------------------------------------------
       
    46 C6to4FlowInfo::C6to4FlowInfo(const TPacketHead &aHead)
       
    47 	: iInterfaceIndex(aHead.iInterfaceIndex)
       
    48 	{
       
    49 	// Need to save the inner selector information which is
       
    50 	// restored at ReadyL.
       
    51 	iSrcPort = aHead.iSrcPort;
       
    52 	iDstPort = aHead.iDstPort;
       
    53 	iIcmpType = aHead.iIcmpType;
       
    54 	iIcmpCode = aHead.iIcmpCode;
       
    55 	iInnerIp = aHead.ip6;
       
    56 	iDstId = aHead.iDstId;
       
    57 	iSrcId = aHead.iSrcId;
       
    58 	}
       
    59 	
       
    60 // ----------------------------------------------------------------------------
       
    61 // C6to4FlowInfo::~C6to4FlowInfo
       
    62 // ----------------------------------------------------------------------------
       
    63 C6to4FlowInfo::~C6to4FlowInfo ()
       
    64 	{
       
    65 	iPacket.Free();
       
    66 	}
       
    67 
       
    68 // ----------------------------------------------------------------------------
       
    69 // 6to4FlowInfo::ReadyL
       
    70 // The stack asks if the flow is ready to send. In the same time, the plugin
       
    71 // configures the source IP address from the flow, including configuring it to
       
    72 // the virtual interface. Set the packet source and destination IP addresses
       
    73 // for the inner (IPv6) header. Set the packet interface index. Set the packet 
       
    74 // next header to be the inner header next header and set the packet IP version
       
    75 // to 6.
       
    76 // ----------------------------------------------------------------------------
       
    77 //
       
    78 TInt C6to4FlowInfo::ReadyL (TPacketHead & aHead)
       
    79 	{
       
    80 	// Save the fixed packet content from the TPacketHead
       
    81 	iOffset = aHead.iOffset;
       
    82 	iPacket.Free();
       
    83 	if (iOffset > 0)
       
    84 		{
       
    85 		iPacket.Assign(aHead.iPacket);
       
    86 		aHead.iOffset = 0;
       
    87 		}
       
    88 
       
    89 	// Save the outer IP information
       
    90 	iOuterIp = aHead.ip6;
       
    91 
       
    92 	// Set inner header source and dest addresses
       
    93 	aHead.ip6 = iInnerIp;
       
    94 	// Inner Version() is not yet set correctly, make it correct.
       
    95 	aHead.ip6.SetVersion(iInnerIp.DstAddr().IsV4Mapped() ? 4 : 6);
       
    96 	aHead.iSrcId = iSrcId;
       
    97 	aHead.iDstId = iDstId;
       
    98 	aHead.iInterfaceIndex = iInterfaceIndex;
       
    99 	// Both next header and iProtocol must have the same value
       
   100 	// as the iPacket is now empty.
       
   101 	aHead.iProtocol = (TUint8)iInnerIp.NextHeader();
       
   102 	aHead.iSrcPort = iSrcPort;
       
   103 	aHead.iDstPort = iDstPort;
       
   104 	aHead.iIcmpType = iIcmpType;
       
   105 	aHead.iIcmpCode = iIcmpCode;
       
   106 	return EFlow_READY;
       
   107 	}
       
   108 
       
   109 // ----------------------------------------------------------------------------
       
   110 // 6to4FlowInfo::ApplyL
       
   111 // Final stage where the 6to4 touches the outgoing packet. Space is made for
       
   112 // the IP header and the IP header is initialized.
       
   113 // ----------------------------------------------------------------------------
       
   114 TInt C6to4FlowInfo::ApplyL (RMBufSendPacket & aPacket, RMBufSendInfo & aInfo)
       
   115 	{
       
   116 	// Apply the tunnelling
       
   117 
       
   118 	// Prepend the fixed content (if any) below the IP header
       
   119 	if (iOffset > 0)
       
   120 		{
       
   121 		RMBufChain work;
       
   122 		// Note: assumed that if CopyL leaves, then work is empty
       
   123 		iPacket.CopyL(work);
       
   124 		aPacket.Prepend(work);
       
   125 		aInfo.iLength += iOffset;
       
   126 		}
       
   127 	switch(iOuterIp.Version())
       
   128 		{
       
   129 		case 6:
       
   130 			{
       
   131 			aPacket.PrependL(sizeof(TInet6HeaderIP));
       
   132 			aInfo.iLength += sizeof(TInet6HeaderIP);
       
   133 			aInfo.iProtocol = KProtocolInet6Ip;
       
   134 
       
   135 			TInet6Packet<TInet6HeaderIP> ip(aPacket);
       
   136 			if (ip.iHdr == NULL)
       
   137 				User::Leave(KErrGeneral);
       
   138 
       
   139 			// Build outer IPv6 header (already in iOuterIp, just copy)
       
   140 			*ip.iHdr = iOuterIp;
       
   141 			// Note: Certain packets must not have ECN ECT bits set. tcp_sap.cpp sets
       
   142 			// KIpNoEcnEct for those packets.
       
   143 			if (aInfo.iFlags & KIpNoEcnEct)
       
   144 				{
       
   145 				ip.iHdr->SetTrafficClass(ip.iHdr->TrafficClass() & 0xfc);
       
   146 				}
       
   147 			ip.iHdr->SetPayloadLength(aInfo.iLength);
       
   148 			break;
       
   149 			}
       
   150 		case 4:
       
   151 			{
       
   152 			// Make space for IPv4 header
       
   153 			aPacket.PrependL (20);
       
   154 			aInfo.iLength += 20;
       
   155 			aInfo.iProtocol = KProtocolInetIp;
       
   156 
       
   157 			TInet6Checksum < TInet6HeaderIP4 > ip (aPacket);
       
   158 			if (ip.iHdr == NULL)
       
   159 				User::Leave (KErrGeneral);
       
   160 
       
   161 			// Build the outer IPv4 header
       
   162 			ip.iHdr->Init(iOuterIp.TrafficClass() & ((aInfo.iFlags & KIpNoEcnEct) ? 0xfc : 0xff));
       
   163 			// Raw Address load. Someone else must have already checked that
       
   164 			// both src and dst are IPv4 mapped addresses at the end of the
       
   165 			// ReadyL phase! This just does a blind copy.
       
   166 			ip.iHdr->DstAddrRef() = iOuterIp.DstAddr().u.iAddr32[3];
       
   167 			ip.iHdr->SrcAddrRef() = iOuterIp.SrcAddr().u.iAddr32[3];
       
   168 
       
   169 			// Somewhat ad hoc thing: if DontFragment flag is set, then
       
   170 			// set the DF bit to the IPv4 header...
       
   171 			if (aInfo.iFlags & KIpDontFragment)
       
   172 				ip.iHdr->SetFlags((TUint8)(ip.iHdr->Flags() | KInet4IP_DF));
       
   173 	
       
   174 			ip.iHdr->SetHeaderLength (20);
       
   175 			ip.iHdr->SetTotalLength (aInfo.iLength);
       
   176 			ip.iHdr->SetTtl(iOuterIp.HopLimit());
       
   177 
       
   178 			// NOTE!!! Something might be done for this. Now it is theoretically
       
   179 			// possible that a same host receives protocol 41 packets from us and
       
   180 			// we have two or more flows with protocol 41 AND two packets get 
       
   181 			// fragmented and are reassembled in the same time by the remote host
       
   182 			// AND the IPv4 identifier happens to be the same. That would break the
       
   183 			// reassembly process, but since this is practically "impossible", it is
       
   184 			// left now without a fix.
       
   185 			ip.iHdr->SetIdentification (iPacketID++);                                                                
       
   186 			ip.iHdr->SetProtocol (iOuterIp.NextHeader());
       
   187 
       
   188 			// Checksum of the outer header.
       
   189 			ip.ComputeChecksum ();
       
   190 			break;
       
   191 			}
       
   192 		default:
       
   193 			User::Leave(KErrGeneral);
       
   194 		}
       
   195 
       
   196 	// Pass the packet
       
   197 	return 0;
       
   198 	}
       
   199 
       
   200 // ----------------------------------------------------------------------------
       
   201 // 6to4FlowInfo::Open
       
   202 // Open the flow, keep reference count.
       
   203 // ----------------------------------------------------------------------------
       
   204 //
       
   205 
       
   206 void C6to4FlowInfo::Open ()
       
   207 	{
       
   208 	iRefs++;
       
   209 	}
       
   210 
       
   211 // ----------------------------------------------------------------------------
       
   212 // 6to4FlowInfo::Close
       
   213 // Close the flow if the reference count has reached zero. Remove the flow 
       
   214 // from any list it is stored.
       
   215 // ----------------------------------------------------------------------------
       
   216 //
       
   217 void C6to4FlowInfo::Close ()
       
   218 	{
       
   219 	if (--iRefs < 0)
       
   220 		{
       
   221 		delete this;
       
   222 		}
       
   223 	}
       
   224 
       
   225 // ========================== OTHER EXPORTED FUNCTIONS ========================
       
   226 
       
   227 //  End of File