diff -r 000000000000 -r 33413c0669b9 vpnengine/kmdserver/src/vpnconnection.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vpnengine/kmdserver/src/vpnconnection.cpp Thu Dec 17 09:14:51 2009 +0200 @@ -0,0 +1,490 @@ +/* +* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: VPN connection specific structures +* +*/ + + +#include +#include + +#include "disconnectionobserver.h" +#include "ikeconnectioninterface.h" +#include "ikedebug.h" +#include "ikeplugindefs.h" +#include "ikepluginsessionhandler.h" +#include "ikepolparser.h" +#include "ikesocketdefs.h" +#include "kmdapi.h" // For error codes +#include "kmdserver.h" + +// CLASS HEADER +#include "vpnconnection.h" + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +CVpnConnection* CVpnConnection::NewLC( TUint32 aVpnIapId, + CKmdServer& aServer, + MIkeDebug& aDebug ) + { + CVpnConnection* self = new ( ELeave ) CVpnConnection( aVpnIapId, + aServer, + aDebug ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// --------------------------------------------------------------------------- +// Destructor. +// --------------------------------------------------------------------------- +// +CVpnConnection::~CVpnConnection() + { + DEBUG_LOG1( _L("CVpnConnection::~CVpnConnection, VPN IAP id=%d"), + iVpnIapId ); + + delete iDisconnectionObserver; + delete iIkeConnection; + + iEventMediator.Close(); + } + +// --------------------------------------------------------------------------- +// Constructor. +// --------------------------------------------------------------------------- +// +CVpnConnection::CVpnConnection( TUint32 aVpnIapId, + CKmdServer& aServer, + MIkeDebug& aDebug ) + : iServer( aServer ), + iVpnIapId( aVpnIapId ), + iDisconnectEventReceived( EFalse ), + iIkePluginSessionHandler( NULL ), + iDebug( aDebug ) + { + DEBUG_LOG1( _L("CVpnConnection::CVpnConnection, VPN IAP id=%d"), + iVpnIapId ); + } + +// --------------------------------------------------------------------------- +// Second phase construction. +// --------------------------------------------------------------------------- +// +void CVpnConnection::ConstructL() + { + User::LeaveIfError( iEventMediator.Connect() ); + + using namespace CMManager; + + RCmManagerExt cmManagerExt; + cmManagerExt.OpenL(); + CleanupClosePushL( cmManagerExt ); + + RCmConnectionMethodExt vpnConnectionMethod = cmManagerExt.ConnectionMethodL( iVpnIapId ); + CleanupClosePushL( vpnConnectionMethod ); + + iVpnNetId = vpnConnectionMethod.GetIntAttributeL( ECmNetworkId ); + iRealIapId = vpnConnectionMethod.GetIntAttributeL( EVpnIapId ); + iRealSnapId = vpnConnectionMethod.GetIntAttributeL( ECmNextLayerSNAPId ); + + CleanupStack::PopAndDestroy( &vpnConnectionMethod ); + CleanupStack::PopAndDestroy( &cmManagerExt ); + + __ASSERT_DEBUG( iRealIapId != 0 || iRealSnapId != 0, User::Invariant() ); + + iIkeConnection = CIkeConnectionInterface::NewL( iDebug ); + iDisconnectionObserver = CDisconnectionObserver::NewL( *iIkeConnection, *this ); + iDisconnectionObserver->StartObserving(); + } + +// --------------------------------------------------------------------------- +// Starts real network connection. +// --------------------------------------------------------------------------- +// +void CVpnConnection::StartRealConnection( TRequestStatus& aStatus ) + { + __ASSERT_DEBUG( iRealIapId != 0 || iRealSnapId != 0, User::Invariant() ); + iIkeConnection->StartConnection( iRealIapId, iRealSnapId, aStatus ); + } + +// --------------------------------------------------------------------------- +// Cancels real connection starting. +// --------------------------------------------------------------------------- +// +void CVpnConnection::CancelStartRealConnection() + { + iIkeConnection->CancelStartConnection(); + } + +// --------------------------------------------------------------------------- +// Resolves an IP address from FQDN address. +// --------------------------------------------------------------------------- +// +void CVpnConnection::ResolveAddress( const TDesC& aFqdn, + TNameEntry& aNameEntry, + TRequestStatus& aStatus ) + { + iIkeConnection->ResolveFQDNAddress( aFqdn, aNameEntry, aStatus ); + } + +// --------------------------------------------------------------------------- +// Cancels resolving. +// --------------------------------------------------------------------------- +// +void CVpnConnection::CancelResolveAddress() + { + iIkeConnection->CancelResolveFQDNAddress(); + } + +// --------------------------------------------------------------------------- +// Starts negotiation with a remote host. +// --------------------------------------------------------------------------- +// +void CVpnConnection::NegotiateWithHost( CIkeData& aIkeData, + TUint32 aVpnInterfaceIndex, + IkeSocket::TIpVersion aIpVersion, + TVPNAddress& aInternalAddress, + TRequestStatus& aStatus ) + { + __ASSERT_DEBUG( iClientStatusNegotiate == NULL, + User::Invariant() ); + + // Store client's request status and internal address. + iClientStatusNegotiate = &aStatus; + *iClientStatusNegotiate = KRequestPending; + iClientInternalAddress = &aInternalAddress; + + TInt err( KErrNone ); + if ( aIkeData.iIkeVersion == KIkeV1 || aIkeData.iIkeVersion == KIkeV2 ) + { + // Create IKE plugin session. + iIkeVersion = aIkeData.iIkeVersion; + + if ( iIkePluginSessionHandler == NULL ) + { + TRAP( err, iIkePluginSessionHandler = &iServer.CreateIkePluginSessionL( iIkeVersion, + aIpVersion, + *iIkeConnection, + iVpnIapId, + iVpnNetId, + aVpnInterfaceIndex, + aIkeData.iDnsServer.Address(), + *this ) ); + } + } + else + { + err = KKmdIkePolicyFileErr; + } + + if ( err != KErrNone ) + { + User::RequestComplete( iClientStatusNegotiate, err ); + iClientStatusNegotiate = NULL; + return; + } + + if ( aIkeData.iAddr.Family() == KAfInet ) + { + aIkeData.iAddr.ConvertToV4Mapped(); + aIkeData.iMask.ConvertToV4Mapped(); + } + aIkeData.iAddr.SetScope( RealNetId() ); + + // Start negotiation. + iIkePluginSessionHandler->NegotiateWithHost( aIkeData ); + } + +// --------------------------------------------------------------------------- +// Cancels negotiation. +// --------------------------------------------------------------------------- +// +void CVpnConnection::CancelNegotiateWithHost() + { + DoCancelNegotiateWithHost(); + } + + +// --------------------------------------------------------------------------- +// Stops VPN connection. +// --------------------------------------------------------------------------- +// +void CVpnConnection::StopVpnConnection( TBool aSilentClose, + TRequestStatus& aStatus ) + { + __ASSERT_DEBUG( iClientStatusStopVpnConnection == NULL, + User::Invariant() ); + + // Store client's request status. + iClientStatusStopVpnConnection = &aStatus; + *iClientStatusStopVpnConnection = KRequestPending; + + DoStopVpnConnection( aSilentClose ); + } + +// --------------------------------------------------------------------------- +// Cancels VPN connection stoppping. VPN Connection is stopped silently. +// --------------------------------------------------------------------------- +// +void CVpnConnection::CancelStopVpnConnection() + { + DoCancelStopVpnConnection(); + } + +// --------------------------------------------------------------------------- +// Gets local address of real network interface. +// --------------------------------------------------------------------------- +// +TInt CVpnConnection::GetLocalAddress( const IkeSocket::TIpVersion aIpVersion, + TInetAddr& aLocalIp ) + { + return iIkeConnection->GetLocalAddress( aIpVersion, aLocalIp ); + } + +// --------------------------------------------------------------------------- +// Returns VPN IAP Id. +// --------------------------------------------------------------------------- +// +TInt CVpnConnection::VpnIapId() const + { + return iVpnIapId; + } + +// --------------------------------------------------------------------------- +// Returns real IAP Id. +// --------------------------------------------------------------------------- +// +TInt CVpnConnection::RealIapId() const + { + return iIkeConnection->IapId(); + } + +// --------------------------------------------------------------------------- +// Returns real NET Id. +// --------------------------------------------------------------------------- +// +TInt CVpnConnection::RealNetId() const + { + return iIkeConnection->NetId(); + } + +// --------------------------------------------------------------------------- +// From class MDisconnectionObserverCallback. +// Notification about link disconnection. VPN connection is stopped. +// --------------------------------------------------------------------------- +// +void CVpnConnection::DisconnectIndication( TInt aStatus ) + { + // Store disconnection status for reporting it to client. + iDisconnectEventReceived = ETrue; + iDisconnectionStatus = aStatus; + + DEBUG_LOG1( _L("Link disconnected, status=%d"), + iDisconnectionStatus ); + + if ( iDisconnectionStatus == KErrNone ) + { + iDisconnectionStatus = KErrDisconnected; + } + + // Stop VPN connection silently. + DoStopVpnConnection( ETrue ); + } + +// --------------------------------------------------------------------------- +// From class MIkePluginSessionHandlerCallback. +// Notification about completion of negotiate request. +// --------------------------------------------------------------------------- +// +void CVpnConnection::NegotiationStarted( TInt aStatus, + const TVPNAddress& aInternalAddress ) + { + __ASSERT_DEBUG( iIkePluginSessionHandler != NULL, + User::Invariant() ); + + DEBUG_LOG1( _L("NegotiateWithHost completed, status=%d"), + aStatus ); + + // Use disconnection status for reporting if set. + if ( iDisconnectEventReceived ) + { + aStatus = iDisconnectionStatus; + } + + if ( iClientStatusNegotiate != NULL ) + { + *iClientInternalAddress = aInternalAddress; + + // Complete client's request. + User::RequestComplete( iClientStatusNegotiate, aStatus ); + iClientInternalAddress = NULL; + iClientStatusNegotiate = NULL; + } + } + +// --------------------------------------------------------------------------- +// From class MIkePluginSessionHandlerCallback. +// Notification about completion of delete session request. IKE plugin +// session object is deleted and real connection stopped. +// --------------------------------------------------------------------------- +// +void CVpnConnection::IkePluginSessionClosed( TInt aStatus ) + { + __ASSERT_DEBUG( iIkePluginSessionHandler != NULL, + User::Invariant() ); + + DEBUG_LOG1( _L("IKE plugin session closed, status=%d"), + aStatus ); + + iServer.DeleteIkePluginSession( iIkeVersion, iVpnIapId ); + iIkePluginSessionHandler = NULL; + + DoStopRealConnection( aStatus ); + } + +// --------------------------------------------------------------------------- +// From class MIkePluginSessionHandlerCallback. +// Notification about IKE plugin session error. +// --------------------------------------------------------------------------- +// +void CVpnConnection::IkePluginSessionError( TInt aStatus ) + { + // Stop VPN connection silently. + DisconnectIndication( aStatus ); + } + +// --------------------------------------------------------------------------- +// Cancels negotiation. +// --------------------------------------------------------------------------- +// +void CVpnConnection::DoCancelNegotiateWithHost() + { + if ( iIkePluginSessionHandler ) + { + iIkePluginSessionHandler->CancelNegotiateWithHost(); + } + } + +// --------------------------------------------------------------------------- +// Stops VPN connection. +// --------------------------------------------------------------------------- +// +void CVpnConnection::DoStopVpnConnection( TBool aSilentClose ) + { + if ( iIkePluginSessionHandler == NULL ) + { + // Stop real connection immediately. + DoStopRealConnection( KErrNone ); + } + else + { + DoCancelNegotiateWithHost(); + + // Delete IKE plugin session first. + DoDeleteSession( aSilentClose ); + } + } + +// --------------------------------------------------------------------------- +// Cancels VPN connection stopping. VPN Connection is stopped silently. +// --------------------------------------------------------------------------- +// +void CVpnConnection::DoCancelStopVpnConnection() + { + DoCancelDeleteSession(); + + if ( iIkePluginSessionHandler != NULL ) + { + iServer.DeleteIkePluginSession( iIkeVersion, iVpnIapId ); + iIkePluginSessionHandler = NULL; + } + + DoStopRealConnection( KErrCancel ); + } + +// --------------------------------------------------------------------------- +// Starts deletion of IKE plugin session. +// --------------------------------------------------------------------------- +// +void CVpnConnection::DoDeleteSession( TBool aSilentClose ) + { + __ASSERT_DEBUG( iIkePluginSessionHandler != NULL, + User::Invariant() ); + + iIkePluginSessionHandler->DeleteSession( aSilentClose ); + } + +// --------------------------------------------------------------------------- +// Cancels deletion of IKE plugin session. IKE plugin session is deleted +// silently. +// --------------------------------------------------------------------------- +// +void CVpnConnection::DoCancelDeleteSession() + { + if ( iIkePluginSessionHandler != NULL ) + { + iIkePluginSessionHandler->CancelDeleteSession(); + } + } + +// --------------------------------------------------------------------------- +// Stops real network connection. +// --------------------------------------------------------------------------- +// +void CVpnConnection::DoStopRealConnection( TInt aStatus ) + { + iDisconnectionObserver->Cancel(); + iIkeConnection->StopConnection(); + + // Use disconnection status for reporting if set. + if ( iDisconnectEventReceived ) + { + aStatus = iDisconnectionStatus; + } + + if ( iClientStatusStopVpnConnection ) + { + // Complete client's request. + User::RequestComplete( iClientStatusStopVpnConnection, aStatus ); + iClientStatusStopVpnConnection = NULL; + } + DoReportDisconnectEvent( aStatus ); + + // Delete VPN connection object. + iServer.DeleteVpnConnection( iVpnIapId ); + } + +// --------------------------------------------------------------------------- +// Reports disconnect event via Event Mediator API. +// --------------------------------------------------------------------------- +// +void CVpnConnection::DoReportDisconnectEvent( TInt aStatus ) + { + TPckg connInfoDes( iVpnIapId ); + TEventData info; + info.iTaskStatus = aStatus; + TPckg infoDes( info ); + + DEBUG_LOG2( _L("Report disconnect event via event mediator, VPN IAP Id=%d, status=%d"), + iVpnIapId, aStatus ); + + iEventMediator.ReportEvent( EKmdRealIapConnDownEvent, + connInfoDes, + infoDes ); + }