|
1 // Copyright (c) 2010 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 // implementation of Inbound and Outbound hook |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalTechnology |
|
21 */ |
|
22 |
|
23 #include <udp_hdr.h> |
|
24 #include <in_chk.h> |
|
25 #include <es_prot_internal.h> |
|
26 #include "tun.pan" |
|
27 #include "tun.h" |
|
28 |
|
29 _LIT(KProtocolTunName, "tun"); |
|
30 |
|
31 void Panic(TTunPanic aPanic) |
|
32 { |
|
33 User::Panic(_L("Tun panic"), aPanic); |
|
34 } |
|
35 |
|
36 |
|
37 // ============================ MEMBER FUNCTIONS ============================== |
|
38 |
|
39 // ---------------------------------------------------------------------------- |
|
40 // CProtocolTun::CProtocolTun |
|
41 // C++ default constructor can NOT contain any code, that |
|
42 // might leave. |
|
43 // ---------------------------------------------------------------------------- |
|
44 // |
|
45 CProtocolTun::CProtocolTun () |
|
46 {} |
|
47 |
|
48 // Destructor |
|
49 CProtocolTun::~CProtocolTun () |
|
50 { |
|
51 NetworkService()->Protocol()->Unbind((CProtocolBase*)iFlowinfo,0); |
|
52 } |
|
53 |
|
54 // ---------------------------------------------------------------------------- |
|
55 // CProtocolTun::NewL |
|
56 // ---------------------------------------------------------------------------- |
|
57 // |
|
58 CProtocolTun* CProtocolTun::NewL () |
|
59 { |
|
60 CProtocolTun* self = new (ELeave) CProtocolTun(); |
|
61 CleanupStack::PushL(self); |
|
62 self -> ConstructL (); |
|
63 CleanupStack::Pop(); |
|
64 return self; |
|
65 } |
|
66 |
|
67 // ---------------------------------------------------------------------------- |
|
68 // CProtocolTun::ConstructL |
|
69 // Initializes the CProtocolTun |
|
70 // ---------------------------------------------------------------------------- |
|
71 // |
|
72 void CProtocolTun::ConstructL () |
|
73 { |
|
74 iFlowinfo = new (ELeave) CTunFlowInfo(); |
|
75 iSapInstance = new (ELeave) CSapTun(); |
|
76 iSapInstance->iFlowInfo= iFlowinfo; |
|
77 iSapInstance->iProtocol=this; |
|
78 } |
|
79 |
|
80 // ---------------------------------------------------------------------------- |
|
81 // CProtocolTun::NetworkAttachedL |
|
82 // Binds the hooks (inbound, outbound flowhook and forward) to the IP6. |
|
83 // ---------------------------------------------------------------------------- |
|
84 // |
|
85 void CProtocolTun::NetworkAttachedL () |
|
86 { |
|
87 // Outbound hook |
|
88 NetworkService()->BindL ((CProtocolBase*) this, BindFlowHook()); |
|
89 } |
|
90 |
|
91 // ---------------------------------------------------------------------------- |
|
92 // CProtocolTun::NetworkDetached |
|
93 // Unbind the hooks. |
|
94 // ---------------------------------------------------------------------------- |
|
95 // |
|
96 void CProtocolTun::NetworkDetached () |
|
97 { |
|
98 // Do Nothing |
|
99 // as the destructor does the rest |
|
100 } |
|
101 |
|
102 // ---------------------------------------------------------------------------- |
|
103 // CProtocolTun::Identify |
|
104 // Provide identification information to the caller. |
|
105 // ---------------------------------------------------------------------------- |
|
106 // |
|
107 void CProtocolTun::Identify (TServerProtocolDesc & aEntry) |
|
108 { |
|
109 aEntry.iName = KProtocolTunName; |
|
110 aEntry.iAddrFamily = KAfInet | KAfInet6; |
|
111 aEntry.iSockType = KSockDatagram; |
|
112 aEntry.iProtocol = KProtocolTUN; |
|
113 aEntry.iVersion = TVersion (1, 0, 0); |
|
114 aEntry.iByteOrder = EBigEndian; |
|
115 aEntry.iServiceInfo=KSIDatagram | KSIConnectionLess; |
|
116 aEntry.iNamingServices = 0; |
|
117 aEntry.iSecurity = KSocketNoSecurity; |
|
118 aEntry.iServiceTypeInfo=0; |
|
119 aEntry.iMessageSize = 0xffff; |
|
120 aEntry.iServiceTypeInfo = ESocketSupport | EInterface; |
|
121 aEntry.iNumSockets = KUnlimitedSockets; |
|
122 } |
|
123 |
|
124 void CProtocolTun::Identify (TServerProtocolDesc * aDesc) const |
|
125 { |
|
126 Identify (*aDesc); |
|
127 } |
|
128 |
|
129 // ---------------------------------------------------------------------------- |
|
130 // CProtocolTun::ApplyL |
|
131 // This is the handler for forwarding packets. |
|
132 // Udp encapsulation for the packets from the Virtual tunnel nif |
|
133 // ---------------------------------------------------------------------------- |
|
134 // |
|
135 TInt CProtocolTun::ApplyL (RMBufHookPacket& /*aPacket*/, RMBufRecvInfo& /*aInfo*/) |
|
136 { |
|
137 return KIp6Hook_PASS; |
|
138 }; |
|
139 |
|
140 // ---------------------------------------------------------------------------- |
|
141 // CProtocolTun:OpenL |
|
142 // Outbound Flow hook Open handler for the protocol. |
|
143 // ---------------------------------------------------------------------------- |
|
144 // |
|
145 MFlowHook *CProtocolTun::OpenL (TPacketHead& /*aHead*/, CFlowContext* aFlow) |
|
146 { |
|
147 // We are interested in this flow, let's create a new local flow instance |
|
148 // create a local copy using copy ctor and return the instance |
|
149 CTunFlowInfo *info = NULL; |
|
150 CNifIfBase* localNifBase = aFlow->Interface(); |
|
151 if(IsPortSet()) |
|
152 { |
|
153 TInetAddr localAddr; |
|
154 localAddr.SetPort(iAppPortNum); |
|
155 TPckg<TInetAddr> pckgLocalAddr(localAddr); |
|
156 if(localNifBase->Control(KSolInetIp,KSoTunnelPort,pckgLocalAddr)== KErrNone) |
|
157 { |
|
158 info = new (ELeave) CTunFlowInfo(iFlowinfo); |
|
159 SetCNifBase(localNifBase); |
|
160 } |
|
161 } |
|
162 return info; |
|
163 } |
|
164 |
|
165 // ---------------------------------------------------------------------------- |
|
166 // CProtocolTun::NewSAPL |
|
167 // Creation of a new SAP instance |
|
168 // ---------------------------------------------------------------------------- |
|
169 // |
|
170 CServProviderBase* CProtocolTun::NewSAPL(TUint /*aProtocol*/) |
|
171 { |
|
172 #if 0 |
|
173 CSapTun *nsap = new(ELeave) CSapTun();//CSapTun::GetInstanceL(); |
|
174 nsap->iProtocol=this; |
|
175 nsap->iFlowInfo= iFlowinfo; |
|
176 #endif |
|
177 return iSapInstance; |
|
178 } |
|
179 |
|
180 /** |
|
181 --------------------------------------------------------------------------------------- |
|
182 CSapTun |
|
183 --------------------------------------------------------------------------------------- |
|
184 |
|
185 This class is derived from CServProviderBase.CSapTun is the service class for sockets |
|
186 loading CProtocolTun.But here only one socket will be able to load protocol.If protocol once |
|
187 loaded other socket cannot service protocol by opening socket. |
|
188 */ |
|
189 |
|
190 //CSapTun* CSapTun::iInstance = NULL; |
|
191 |
|
192 CSapTun::CSapTun() |
|
193 { } |
|
194 #if 0 |
|
195 CSapTun* CSapTun::GetInstanceL() |
|
196 { |
|
197 if(!iInstance) |
|
198 { |
|
199 iInstance = new (ELeave) CSapTun(); |
|
200 } |
|
201 return iInstance; |
|
202 } |
|
203 #endif |
|
204 TInt CSapTun::SetOption(TUint aName ,TUint aLevel ,const TDesC8& anOption) |
|
205 /** |
|
206 * This class is used to set PortNumber information to be used by the hook to perform |
|
207 * UDP encapsulation. |
|
208 * @param aName -- KSoTunnelPort |
|
209 * @param aLevel --KSolInetIp. |
|
210 * return - KErrNone if no value is assigned else KErrPermissionDenied |
|
211 **/ |
|
212 |
|
213 { |
|
214 TInt err = KErrNotSupported; |
|
215 if((aName == KSoTunnelPort) && (aLevel == KSolInetIp)) |
|
216 { |
|
217 const TUint opt = *reinterpret_cast<const TUint*>(anOption.Ptr()); |
|
218 iProtocol->SetAppPortNum(opt); |
|
219 iFlowInfo->SetAppPortNum(opt); |
|
220 err= KErrNone; |
|
221 } |
|
222 return err; |
|
223 } |
|
224 |
|
225 TInt CSapTun::SecurityCheck(MProvdSecurityChecker* aChecker) |
|
226 /** |
|
227 * Capability check for the TUN Hook sockets. |
|
228 * |
|
229 * TUN Hook sockets require the NetworkControl capability. |
|
230 * |
|
231 * @param aChecker The policy checker. |
|
232 * @return The result of the policy check. |
|
233 */ |
|
234 { |
|
235 // This method is called when a SAP is created and when a socket is transferred between sessions. The SAP is |
|
236 //required to check whether the originating client process has enough privileges to request services from the SAP. |
|
237 //The MProvdSecurityChecker class instance is used to perform security policy checks. The SAP may choose |
|
238 //to perform a security policy check in its SecurityCheck(...) method, or it may choose to store the |
|
239 //MProvdSecurityChecker class instance argument and perform checking later (i.e. when subsequent |
|
240 //SAP methods are called). |
|
241 _LIT_SECURITY_POLICY_C1(KPolicyNetworkControl, ECapabilityNetworkControl); |
|
242 return aChecker->CheckPolicy(KPolicyNetworkControl, "TUN Hook Loading failed."); |
|
243 } |
|
244 |
|
245 /* |
|
246 ------------------------------------------------------------------------------------------ |
|
247 |
|
248 SAP UNUSED FUNTION SECTION |
|
249 ------------------------------------------------------------------------------------------ |
|
250 |
|
251 SAP definion which are not being used.These functions are not doing anything instead they are |
|
252 returning nothing from it. |
|
253 |
|
254 */ |
|
255 |
|
256 void CSapTun::Ioctl(TUint /*level*/,TUint /*name*/,TDes8*/*anOption*/) |
|
257 {} |
|
258 |
|
259 void CSapTun::Start() |
|
260 {} |
|
261 |
|
262 void CSapTun::Shutdown(TCloseType /*option*/) |
|
263 {} |
|
264 |
|
265 void CSapTun::LocalName(TSockAddr& /*anAddr*/) const |
|
266 {} |
|
267 |
|
268 TInt CSapTun::SetLocalName(TSockAddr& /*anAddr*/) |
|
269 { |
|
270 return KErrNotSupported; |
|
271 } |
|
272 |
|
273 void CSapTun::RemName(TSockAddr& /*anAddr*/) const |
|
274 {} |
|
275 |
|
276 TInt CSapTun::SetRemName(TSockAddr& /*anAddr*/) |
|
277 { |
|
278 return KErrNotSupported; |
|
279 } |
|
280 |
|
281 TInt CSapTun::GetOption(TUint /*aLevel*/, TUint /*aName*/, TDes8& /*aOption*/)const |
|
282 /** |
|
283 * This implements GetOption method for Napt specific service provider. |
|
284 * @param aLevel |
|
285 * @param aName |
|
286 * @param anOption |
|
287 * @return KErrNone in case of success |
|
288 **/ |
|
289 { |
|
290 return KErrNone; |
|
291 } |
|
292 |
|
293 |
|
294 void CSapTun::ActiveOpen() |
|
295 {} |
|
296 |
|
297 TInt CSapTun::PassiveOpen(TUint /*aQueSize*/) |
|
298 { |
|
299 return KErrNotSupported; |
|
300 } |
|
301 |
|
302 void CSapTun::Shutdown(TCloseType /*option*/,const TDesC8& /*aDisconnectionData*/) |
|
303 {} |
|
304 |
|
305 void CSapTun::AutoBind() |
|
306 {} |
|
307 |
|
308 TInt CSapTun::PassiveOpen(TUint /*aQueSize*/,const TDesC8& /*aConnectionData*/) |
|
309 { |
|
310 return KErrNotSupported; |
|
311 } |
|
312 |
|
313 void CSapTun::ActiveOpen(const TDesC8& /*aConnectionData*/) |
|
314 {} |
|
315 |
|
316 void CSapTun::CancelIoctl(TUint /*aLevel*/,TUint /*aName*/) |
|
317 {} |
|
318 |
|
319 CSapTun::~CSapTun() |
|
320 { |
|
321 } |
|
322 |
|
323 // TUN OUTBOUND FLOW HOOK functions. |
|
324 |
|
325 // ---------------------------------------------------------------------------- |
|
326 // CTunFlowInfo::CTunFlowInfo |
|
327 // ---------------------------------------------------------------------------- |
|
328 CTunFlowInfo::CTunFlowInfo () |
|
329 {} |
|
330 |
|
331 // ---------------------------------------------------------------------------- |
|
332 // CTunFlowInfo::~CTunFlowInfo |
|
333 // ---------------------------------------------------------------------------- |
|
334 CTunFlowInfo::~CTunFlowInfo () |
|
335 {} |
|
336 |
|
337 // ---------------------------------------------------------------------------- |
|
338 // CTunFlowInfo::ReadyL |
|
339 // The stack asks if the flow is ready to send. |
|
340 // ---------------------------------------------------------------------------- |
|
341 // |
|
342 TInt CTunFlowInfo::ReadyL (TPacketHead& /*aHead*/) |
|
343 { |
|
344 return EFlow_READY; |
|
345 } |
|
346 |
|
347 // ---------------------------------------------------------------------------- |
|
348 // CTunFlowInfo::ApplyL |
|
349 // Intial stage where the CTunFlowInfo touches the outgoing packet. |
|
350 // ---------------------------------------------------------------------------- |
|
351 TInt CTunFlowInfo::ApplyL(RMBufSendPacket & aPacket, RMBufSendInfo & aInfo) |
|
352 { |
|
353 const TInetAddr& dest = aInfo.iDstAddr; |
|
354 const TInetAddr& src = aInfo.iSrcAddr; |
|
355 |
|
356 TInt protocol = aInfo.iProtocol; |
|
357 |
|
358 // protocolnum check is added to avoid loopin in the same hook as the |
|
359 // source and destination address will not be changed in the RMBufSendInfo. |
|
360 if (dest.Address() == src.Address()) |
|
361 { |
|
362 if (protocol == KProtocolInetIp ) |
|
363 { |
|
364 TInet6Packet<TInet6HeaderIP4> localIP(aPacket); |
|
365 TUint protocol = localIP.iHdr->Protocol(); |
|
366 |
|
367 if (protocol == KProtocolInetUdp) |
|
368 { |
|
369 TInet6HeaderUDP* udpHdr = (TInet6HeaderUDP*) localIP.iHdr->EndPtr(); |
|
370 TUint srcPort = udpHdr->SrcPort(); |
|
371 |
|
372 if (srcPort == iAppPortNum) |
|
373 { |
|
374 // Ingress traffic forwarded from TUN Client Application. Trim the |
|
375 // outer header and send the original pkt back to the ip stack. |
|
376 TInt outerHdrLen = TInet6HeaderIP4::MinHeaderLength() + TInet6HeaderUDP::MinHeaderLength(); |
|
377 |
|
378 // the info length will be updated by TrimStart |
|
379 aPacket.TrimStart(outerHdrLen); |
|
380 |
|
381 TInet6Packet<TInet6HeaderIP4> ip(aPacket); |
|
382 //Update the info Address information |
|
383 TInetAddr::Cast(aInfo.iSrcAddr).SetAddress(ip.iHdr->SrcAddr()); |
|
384 TInetAddr::Cast(aInfo.iDstAddr).SetAddress(ip.iHdr->DstAddr()); |
|
385 |
|
386 // restart the hook processing from the begining. |
|
387 return KIp6Hook_DONE; |
|
388 } |
|
389 } |
|
390 } |
|
391 #ifdef IPV6SUPPORT |
|
392 else if (protocol == KProtocolInet6Ip) |
|
393 { |
|
394 TInet6Packet<TInet6HeaderIP> localIP6(aPacket); |
|
395 TInt protocol = localIP6.iHdr->NextHeader(); |
|
396 if (protocol == KProtocolInetUdp) |
|
397 { |
|
398 TInet6HeaderUDP* udpHdr = |
|
399 (TInet6HeaderUDP*) localIP6.iHdr->EndPtr(); |
|
400 TUint srcPort = udpHdr->SrcPort(); |
|
401 |
|
402 if (srcPort == iAppPortNum) |
|
403 { |
|
404 // Ingress traffic forwarded from TUN Client Application. Trim the |
|
405 // outer header and send the original pkt back to the ip stack. |
|
406 TInt outerHdrLen = TInet6HeaderIP::MinHeaderLength() |
|
407 + TInet6HeaderUDP::MinHeaderLength(); |
|
408 |
|
409 // the info length will be updated by TrimStart |
|
410 aPacket.TrimStart(outerHdrLen); |
|
411 |
|
412 TInet6Packet<TInet6HeaderIP> ip6(aPacket); |
|
413 //Update the info Address information |
|
414 TInetAddr::Cast(aInfo.iSrcAddr).SetAddress(ip6.iHdr->SrcAddr()); |
|
415 TInetAddr::Cast(aInfo.iDstAddr).SetAddress(ip6.iHdr->DstAddr()); |
|
416 |
|
417 // restart the hook processing from the begining. |
|
418 return KIp6Hook_DONE; |
|
419 } |
|
420 else |
|
421 { |
|
422 return KIp6Hook_PASS; |
|
423 } |
|
424 } |
|
425 } |
|
426 #endif //IPV6SUPPORT |
|
427 else |
|
428 { |
|
429 Panic(ETunPanic_BadHeader); |
|
430 } |
|
431 } |
|
432 else |
|
433 { |
|
434 // Outgoing packet from the application to the TUN Client Application |
|
435 // need to mark this packet to be handled at Forward hook. |
|
436 |
|
437 if (protocol == KProtocolInetIp) |
|
438 { |
|
439 TInet6Packet<TInet6HeaderIP4> ip(aPacket); |
|
440 TInt tmpTos = ip.iHdr->TOS(); |
|
441 tmpTos |= KTunTos; |
|
442 ip.iHdr->SetTOS(tmpTos); |
|
443 TInet6Checksum<TInet6HeaderIP4> lIp(aPacket); |
|
444 lIp.ComputeChecksum(); // recompute checksum as TOS field is updated |
|
445 } |
|
446 #ifdef IPV6SUPPORT |
|
447 else if (protocol == KProtocolInet6Ip) |
|
448 { |
|
449 TInet6Packet<TInet6HeaderIP> ip6(aPacket); |
|
450 TInt tmpTrafficClass = ip6.iHdr->TrafficClass(); |
|
451 tmpTrafficClass |= KTunTos; |
|
452 ip6.iHdr->SetTrafficClass(tmpTrafficClass); |
|
453 // No need to update checksum in case of IPV6 |
|
454 } |
|
455 #endif //IPV6SUPPORT |
|
456 else |
|
457 { |
|
458 Panic(ETunPanic_BadHeader); |
|
459 } |
|
460 return KIp6Hook_PASS; |
|
461 } |
|
462 |
|
463 return KIp6Hook_PASS; |
|
464 } |
|
465 |
|
466 |
|
467 // ---------------------------------------------------------------------------- |
|
468 // CTunFlowInfo::Open |
|
469 // Open the flow, keep reference count. |
|
470 // ---------------------------------------------------------------------------- |
|
471 // |
|
472 |
|
473 void CTunFlowInfo::Open () |
|
474 { |
|
475 iRef++; |
|
476 } |
|
477 |
|
478 // ---------------------------------------------------------------------------- |
|
479 // CTunFlowInfo::Close |
|
480 // Close the flow if the reference count has reached zero. Remove the flow |
|
481 // from any list it is stored. |
|
482 // ---------------------------------------------------------------------------- |
|
483 // |
|
484 void CTunFlowInfo::Close () |
|
485 { |
|
486 if (--iRef < 0) |
|
487 { |
|
488 delete this; |
|
489 } |
|
490 } |
|
491 |