tcpiputils/tun/src/tun.cpp
branchRCL_3
changeset 63 425d8f4f7fa5
equal deleted inserted replaced
58:8d540f55e491 63:425d8f4f7fa5
       
     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