|
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 |