vpnengine/ikeutils/src/pfkeysocketif.cpp
changeset 0 33413c0669b9
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     1 /*
       
     2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of VPN PFKEY socket interface
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <es_sock.h>
       
    20 #include <in_sock.h>
       
    21 #include <eikenv.h>
       
    22 #include <pfkey_send.h>
       
    23 #include <random.h>
       
    24 #include "pfkeysocketif.h"
       
    25 #include "pfkeymsg.h"
       
    26 #include "ipsecsadata.h"
       
    27 #include "ipsecsalifetime.h"
       
    28 #include "ikedebug.h"
       
    29 
       
    30 const TInt KDefaultPID( 0x2001E609 ); // UID3 of ikeutils.dll
       
    31 
       
    32 // ======== MEMBER FUNCTIONS ========
       
    33 
       
    34 EXPORT_C CPFKeySocketIf* CPFKeySocketIf::NewL( MPFKeyMessageListener* aListener,
       
    35                                                MIkeDebug& aDebug )
       
    36     {
       
    37     CPFKeySocketIf* reader = new ( ELeave ) CPFKeySocketIf( aListener, aDebug );
       
    38     CleanupStack::PushL( reader );
       
    39     reader->ConstructL();
       
    40     CleanupStack::Pop( reader );        
       
    41     return reader;
       
    42     }
       
    43 
       
    44 //
       
    45 // CPFKeySocketIf::~CPFKeySocketIf
       
    46 //
       
    47 CPFKeySocketIf::~CPFKeySocketIf()
       
    48     {
       
    49     Cancel();
       
    50     iPendingSpiRequests.Close();
       
    51     iSadb.Close();
       
    52     iSocketServer.Close();
       
    53     }
       
    54 
       
    55 //
       
    56 // CPFKeySocketIf::CPFKeySocketIf
       
    57 //
       
    58 CPFKeySocketIf::CPFKeySocketIf( MPFKeyMessageListener* aListener,
       
    59                                 MIkeDebug& aDebug )
       
    60 : CActive( EPriorityNormal ),
       
    61   iListener( aListener ),
       
    62   iSeq( 0 ),
       
    63   iDebug( aDebug )
       
    64     {
       
    65     CActiveScheduler::Add( this );
       
    66     }
       
    67     
       
    68 //
       
    69 // CPFKeySocketIf::ConstructL()
       
    70 // Open and activate the socket input
       
    71 //
       
    72 void CPFKeySocketIf::ConstructL()
       
    73     {   
       
    74     TPtr8 ptr( (TUint8*)&iSpiBase, sizeof( iSpiBase ) );
       
    75     ptr.SetLength( sizeof( iSpiBase ) );
       
    76     TRandom::RandomL( ptr );
       
    77     iSpiBase &= 0x7fffffff;
       
    78     
       
    79     User::LeaveIfError( iSocketServer.Connect() ); 
       
    80     User::LeaveIfError( iSadb.Open( iSocketServer ) );
       
    81 
       
    82     //
       
    83     // Register for ACQUIRE messages
       
    84     //
       
    85     TPfkeySendMsg reg( SADB_REGISTER, SADB_SATYPE_ESP, ++iSeq, KDefaultPID );
       
    86     TRequestStatus status;
       
    87 	iSadb.FinalizeAndSend( reg, status );
       
    88     User::WaitForRequest( status );
       
    89     DEBUG_LOG1( _L("Register for ESP, status=%d"), iStatus.Int() );
       
    90     
       
    91     iMsg.Reset();
       
    92     iSadb.ReadRequest( iMsg, iStatus );
       
    93     SetActive();
       
    94     }
       
    95     
       
    96     
       
    97 void CPFKeySocketIf::GetSpi( const TUint8 aType,
       
    98                              const TUint32 aSeq,
       
    99                              const TInetAddr& aSrc,
       
   100                              const TInetAddr& aDst,
       
   101                              TUint32& aSpi,
       
   102                              TRequestStatus& aClientStatus)
       
   103     {
       
   104     /*Params:
       
   105             aType:SADB_SATYPE_AH,SADB_SATYPE_ESP from prop_II
       
   106             aSeq: Seq number for the message
       
   107             aSrc,aDst: Src & dst addresses
       
   108     */
       
   109     TRequestStatus status;
       
   110     TUint32 start = NewSpi();
       
   111 
       
   112 	TPfkeySendMsg msg( SADB_GETSPI, aType, aSeq, (TUint32)&aClientStatus );
       
   113     msg.Add( Int2Type<SADB_EXT_ADDRESS_SRC>(), aSrc );
       
   114     msg.Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aDst );
       
   115     msg.Add( Int2Type<SADB_EXT_SPIRANGE>(), start );
       
   116     
       
   117     aClientStatus = KRequestPending;
       
   118     TPendingSpiRequest pendingSpiRequest(aSpi, aClientStatus);
       
   119     TInt err = iPendingSpiRequests.Append(pendingSpiRequest);
       
   120     
       
   121     if (err == KErrNone)
       
   122         {
       
   123         iSadb.FinalizeAndSend( msg, status );
       
   124         User::WaitForRequest( status );
       
   125         }
       
   126     else
       
   127         {
       
   128         TRequestStatus* status = &aClientStatus;
       
   129         User::RequestComplete(status, err);
       
   130         }
       
   131     }
       
   132 
       
   133 
       
   134 void CPFKeySocketIf::CancelGetSpi(TRequestStatus& aClientStatus)
       
   135     {
       
   136     for (TInt i = 0; i < iPendingSpiRequests.Count(); ++i)
       
   137         {
       
   138         TPendingSpiRequest& pendingSpiRequest = iPendingSpiRequests[i];
       
   139         if (&pendingSpiRequest.iClientStatus == &aClientStatus)
       
   140             {
       
   141             pendingSpiRequest.iSpi = 0;
       
   142             TRequestStatus* status = &pendingSpiRequest.iClientStatus;
       
   143             iPendingSpiRequests.Remove(i);
       
   144             User::RequestComplete(status, KErrCancel);
       
   145             break;
       
   146             }
       
   147         }
       
   148     }
       
   149 
       
   150 
       
   151 // Sends Acquire with errno informing about key management failure.
       
   152 EXPORT_C void CPFKeySocketIf::AcquireSAError( const TIpsecSAData& aSAData,
       
   153                                               const TInt aError )
       
   154  	 {
       
   155      TRequestStatus status;
       
   156      TInt err = -aError;
       
   157      TPfkeySendMsg msg( SADB_ACQUIRE,
       
   158                         aSAData.iSAType,
       
   159                         aSAData.iSeq,
       
   160                         aSAData.iPid );
       
   161 
       
   162      struct sadb_msg& msgHdr = msg.MsgHdr();
       
   163      msgHdr.sadb_msg_errno = (TUint8) err;
       
   164      msgHdr.sadb_msg_reserved = (TUint16) ( err>>8 );
       
   165      
       
   166      msg.Add( Int2Type<SADB_EXT_SA>(), aSAData.iSPI );
       
   167      msg.Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aSAData.iDst );     
       
   168      iSadb.FinalizeAndSend( msg, status );
       
   169      User::WaitForRequest( status );
       
   170  	 }
       
   171 
       
   172 EXPORT_C void CPFKeySocketIf::UpdateSAL( const TIpsecSAData& aSAData )
       
   173     {
       
   174     AddUpdateSAL( SADB_UPDATE, aSAData );
       
   175     }
       
   176 
       
   177 EXPORT_C void CPFKeySocketIf::AddSAL( const TIpsecSAData& aSAData )
       
   178     {
       
   179     AddUpdateSAL( SADB_ADD, aSAData );
       
   180     }
       
   181 
       
   182 EXPORT_C void CPFKeySocketIf::DeleteSA( const TUint32 aSPI,
       
   183                                         const TInetAddr& aSrc,
       
   184                                         const TInetAddr& aDst,
       
   185                                         const TUint8 aProtocol )
       
   186     {
       
   187     TRequestStatus status;
       
   188 	TPfkeySendMsg msg( SADB_DELETE,
       
   189 	                   aProtocol );
       
   190 	msg.Add( Int2Type<SADB_EXT_SA>(), aSPI );
       
   191 	msg.Add( Int2Type<SADB_EXT_ADDRESS_SRC>(), aSrc );
       
   192 	msg.Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aDst );
       
   193 	iSadb.FinalizeAndSend( msg, status );
       
   194 	User::WaitForRequest( status );
       
   195     }
       
   196 
       
   197 EXPORT_C void CPFKeySocketIf::FlushSAs()
       
   198     {
       
   199     TRequestStatus status;
       
   200 	TPfkeySendMsg msg( SADB_FLUSH,
       
   201 	                   SADB_SATYPE_UNSPEC,
       
   202 	                   ++iSeq,
       
   203 	                   KDefaultPID );
       
   204 	iSadb.FinalizeAndSend( msg, status );
       
   205     User::WaitForRequest( status );
       
   206 	DEBUG_LOG1( _L("Request FLUSH, iStatus=%d"), iStatus.Int() );	    
       
   207     }
       
   208 
       
   209 //Updates an SA from the SA database.
       
   210 //SPI in Net order.
       
   211 void CPFKeySocketIf::AddUpdateSAL( const TUint8 aType,
       
   212                                    const TIpsecSAData &aSAData )
       
   213     {
       
   214     TRequestStatus status;
       
   215     TPfkeySendMsg* msg = new( ELeave ) TPfkeySendMsg( aType,
       
   216                                                       aSAData.iSAType,
       
   217                                                       aSAData.iSeq,
       
   218                                                       aSAData.iPid );
       
   219     msg->Add( Int2Type<SADB_EXT_SA>(),
       
   220               aSAData.iSPI,
       
   221               aSAData.iAuthAlg,
       
   222               aSAData.iEncrAlg,
       
   223               SADB_SASTATE_MATURE,
       
   224               aSAData.iReplayWindowLength,
       
   225               aSAData.iFlags );
       
   226     
       
   227     if( aSAData.iHard )
       
   228         {
       
   229         msg->Add( Int2Type<SADB_EXT_LIFETIME_HARD>(), 
       
   230                   aSAData.iHard->iAllocations, 
       
   231                   aSAData.iHard->iBytes, 
       
   232                   aSAData.iHard->iAddtime, 
       
   233                   aSAData.iHard->iUsetime);
       
   234         }
       
   235     if( aSAData.iSoft )
       
   236         {
       
   237         msg->Add( Int2Type<SADB_EXT_LIFETIME_SOFT>(),
       
   238                   aSAData.iSoft->iAllocations, 
       
   239                   aSAData.iSoft->iBytes, 
       
   240                   aSAData.iSoft->iAddtime,
       
   241                   aSAData.iSoft->iUsetime);
       
   242         }
       
   243     msg->Add( Int2Type<SADB_EXT_ADDRESS_SRC>(),
       
   244               aSAData.iSrc,
       
   245               aSAData.iProtocol );
       
   246     msg->Add( Int2Type<SADB_EXT_ADDRESS_DST>(),
       
   247               aSAData.iDst,
       
   248               aSAData.iProtocol );
       
   249     
       
   250     // Deliver internal address for IPSEC4 
       
   251     if ( aSAData.iFlags & SADB_SAFLAGS_INT_ADDR )
       
   252        msg->Add( Int2Type<SADB_EXT_ADDRESS_PROXY>(),
       
   253                  aSAData.iInternalAddress );
       
   254     
       
   255     if ( aSAData.iAuthKey.Length() > 0 )
       
   256         {
       
   257         msg->Add( Int2Type<SADB_EXT_KEY_AUTH>(),
       
   258                   aSAData.iAuthKey );
       
   259         }
       
   260     if ( aSAData.iEncrKey.Length() > 0 )
       
   261         {
       
   262         msg->Add( Int2Type<SADB_EXT_KEY_ENCRYPT>(),
       
   263                   aSAData.iEncrKey );
       
   264         }
       
   265     if ( aSAData.iSrcIdent.Length() > 0 )
       
   266         {
       
   267         msg->Add( Int2Type<SADB_EXT_IDENTITY_SRC>(),
       
   268                   aSAData.iSrcIdent,
       
   269                   aSAData.iSrcIdType );
       
   270         }
       
   271     if ( aSAData.iDstIdent.Length() > 0 )
       
   272         {
       
   273         msg->Add( Int2Type<SADB_EXT_IDENTITY_DST>(),
       
   274                   aSAData.iDstIdent,
       
   275                   aSAData.iDstIdType );
       
   276         }
       
   277 
       
   278     // Deliver generic private PFKEY API extension, if exist.
       
   279     // In this phase extension can consists NAT traversal information for ESP UDP encapsulation (done by IPSEC)
       
   280     if ( aSAData.iGenericExtension.Length() )
       
   281         {
       
   282         msg->Add( Int2Type<SADB_PRIV_GENERIC_EXT>(),
       
   283                   aSAData.iGenericExtension );
       
   284         }
       
   285     
       
   286     iSadb.FinalizeAndSend( *msg, status );
       
   287     User::WaitForRequest( status );
       
   288     delete msg;
       
   289     }
       
   290 
       
   291 TUint32 CPFKeySocketIf::NewSpi()
       
   292     {
       
   293     iSpiBase++;
       
   294     return iSpiBase;
       
   295     }
       
   296 
       
   297 //
       
   298 // SocketReader::ShowMessage
       
   299 //  Output actual "payload" messages (e.g. PFKEY)
       
   300 //
       
   301 #ifdef _DEBUG       
       
   302 void CPFKeySocketIf::ShowMessageL( TPfkeyRecvMsg &aMsg )
       
   303     {
       
   304     HBufC* buffer = HBufC::NewL( 1000 );
       
   305     TPtr str( buffer->Des() );
       
   306     TPfkeyMessage msg( aMsg );
       
   307 
       
   308     if ( msg.iError )
       
   309         {
       
   310         str.Format( _L("Received malformed PFKEY msg of %d bytes: %d\n"),
       
   311                 aMsg.Length(), msg.iError );
       
   312         }   
       
   313     else
       
   314         {
       
   315         msg.iBase.String( str, _L(" ") );
       
   316         msg.iSa.String( str, _L(" ") );
       
   317         msg.iCurrent.String( str, _L(" C=") );
       
   318         msg.iHard.String( str, _L(" H=") );
       
   319         msg.iSoft.String( str, _L(" S=") );
       
   320         msg.iSrcAddr.String( str, _L(" SRC=") );
       
   321         msg.iDstAddr.String( str, _L(" DST=") );
       
   322         msg.iProxyAddr.String( str, _L(" PROXY=") );
       
   323         msg.iAuthKey.String( str, _L(" AUTHKEY=") );
       
   324         msg.iEncryptKey.String( str, _L(" ENCRYPTKEY=") );
       
   325         msg.iSrcIdent.String( str, _L(" SRCI=") );
       
   326         msg.iDstIdent.String( str, _L(" DSTI=") );
       
   327         msg.iSensitivity.String( str, _L(" SENS=") );
       
   328         msg.iProposal.String( str, _L(" PROP=") );
       
   329         msg.iAuthAlgs.String( str, _L(" AUTH=") );
       
   330         msg.iEncryptAlgs.String( str, _L(" ENCR=") );
       
   331         msg.iSpirange.String( str, _L(" SPIR=") );
       
   332         msg.iTs.String( str, _L(" TS=") );
       
   333         msg.iPrivateExtension.String( str, _L(" GEN_EXT=") );
       
   334         }
       
   335     DEBUG_LOG( str );
       
   336     
       
   337     delete buffer;
       
   338     buffer = NULL;
       
   339     }
       
   340 #endif    
       
   341 
       
   342 //
       
   343 // CPFKeySocketIf::RunL
       
   344 //  Called when request completed
       
   345 //
       
   346 void CPFKeySocketIf::RunL()
       
   347     {
       
   348     if ( iStatus.Int() != KErrNone )
       
   349         {
       
   350         DEBUG_LOG1( _L("Socket read, iStatus=%d"), iStatus.Int() );    
       
   351         }
       
   352 
       
   353 #ifdef _DEBUG    
       
   354     TRAP_IGNORE( ShowMessageL( iMsg ) );
       
   355 #endif    
       
   356             
       
   357     TPfkeyMessage msg(iMsg);
       
   358     if ( ( msg.iError == KErrNone ) &&
       
   359          ( msg.iBase.iMsg->sadb_msg_errno == KErrNone ) ) // No error
       
   360         {
       
   361         switch ( msg.iBase.iMsg->sadb_msg_type )
       
   362             {
       
   363             case SADB_GETSPI:
       
   364                 for (TInt i = 0; i < iPendingSpiRequests.Count(); ++i)
       
   365                     {
       
   366                     TPendingSpiRequest& pendingSpiRequest = iPendingSpiRequests[i];
       
   367                     if ((TUint32)&pendingSpiRequest.iClientStatus == msg.iBase.iMsg->sadb_msg_pid)
       
   368                         {
       
   369                         pendingSpiRequest.iSpi = msg.iSa.iExt->sadb_sa_spi;
       
   370                         TRequestStatus* status = &pendingSpiRequest.iClientStatus;
       
   371                         iPendingSpiRequests.Remove(i);
       
   372                         User::RequestComplete(status, KErrNone);
       
   373                         break;
       
   374                         }
       
   375                     }
       
   376                 break;
       
   377             case SADB_ADD:     // Fall through
       
   378             case SADB_UPDATE:  // Fall through
       
   379             case SADB_ACQUIRE: // Fall through
       
   380             case SADB_EXPIRE:  // Fall through               
       
   381                 iListener->PfkeyMessageReceived( msg );
       
   382                 break;
       
   383 
       
   384             default:
       
   385                 break;
       
   386             }       
       
   387         }
       
   388     else
       
   389         {   
       
   390         DEBUG_LOG2( _L("Error in Pfkey message, iError=%d, sadb_msg_errno=%d"),
       
   391                 iStatus.Int(), msg.iBase.iMsg->sadb_msg_errno );
       
   392         }
       
   393     iMsg.Reset();
       
   394     iSadb.ReadRequest( iMsg, iStatus ); // Start a new read
       
   395     SetActive();
       
   396     }
       
   397 
       
   398 //
       
   399 // CPFKeySocketIf::DoCancel
       
   400 //  Called when a pending request should be cancelled
       
   401 //
       
   402 void CPFKeySocketIf::DoCancel()
       
   403     {
       
   404     iSadb.CancelRecv();
       
   405     }
       
   406 
       
   407 //
       
   408 // CPFKeySocketIf::RunError
       
   409 // Called when RunL() leaves 
       
   410 //
       
   411 TInt CPFKeySocketIf::RunError( TInt aError )
       
   412     {
       
   413     DEBUG_LOG1( _L("CPFKeySocketIf::RunError() aError=%d, PFKEY message lost"),
       
   414             aError );
       
   415     aError = aError;
       
   416 
       
   417     iMsg.Reset();
       
   418     iSadb.ReadRequest( iMsg, iStatus ); // Start a new read. 
       
   419     SetActive();
       
   420     
       
   421     return KErrNone; // Active scheduler Error() method NOT called              
       
   422     }
       
   423