vpnengine/vpnconnagt/src/vpnconnagt.cpp
changeset 0 33413c0669b9
child 2 ef893827b4d1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/vpnconnagt/src/vpnconnagt.cpp	Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,805 @@
+/*
+* Copyright (c) 2000-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 Agent
+*
+*/
+
+
+
+#include <cmmanager.h>
+#include <cmconnectionmethod.h>
+#include <cmpluginvpndef.h>
+#include <commdbconnpref.h>
+#include <in_iface.h>
+#include <tunnelnifvar.h>
+#include <d32dbmsconstants.h>
+
+#include "vpnconnagt.h"
+
+
+/***************CVPNConnAgtFactory********************/
+
+extern "C" EXPORT_C CNifAgentFactory* NewAgentFactoryL()
+    {   
+    return new(ELeave) CVPNConnAgtFactory;
+    }
+
+void CVPNConnAgtFactory::InstallL() 
+    {
+    }
+ 
+CNifAgentBase* CVPNConnAgtFactory::NewAgentL(
+    const TDesC& /*aName*/)
+    {
+    return CVPNConnAgt::NewL();
+    }
+
+TInt CVPNConnAgtFactory::Info(
+    TNifAgentInfo&  aInfo, 
+    TInt            /*aIndex*/) const
+    {
+    aInfo.iName = KVPNConnAgtName;
+    aInfo.iVersion = TVersion(KMajorVerNumber,KMinorVerNumber,KBuildVerNumber);
+    return KErrNone;
+    }
+
+/***************CVPNConnAgt********************/
+
+// ---------------------------------------------------------------------------
+// CVPNConnAgt 
+// ---------------------------------------------------------------------------
+//
+CVPNConnAgt::CVPNConnAgt() :
+    iServiceStartedCallback(CActive::EPriorityStandard),
+    iConnectCompleteCallback(CActive::EPriorityStandard), 
+    iDisconnectCallback(CActive::EPriorityStandard)
+    {
+    TCallBack serviceStartedCallback(ServiceStartedCb, this);
+    iServiceStartedCallback.Set(serviceStartedCallback);
+    
+    TCallBack connectionCompleteCallback(ConnectCompleteCb, this);
+    iConnectCompleteCallback.Set(connectionCompleteCallback);
+
+    TCallBack disconnectionCompleteCallback(DisconnectCompleteCb, this);
+    iDisconnectCallback.Set(disconnectionCompleteCallback);
+
+    iEventActivatedClose = EFalse;
+    iDisconnectType = (TDeactivateType)NORMAL_DISCONNECT_MODE; // means the normal way to shutdown
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor 
+// ---------------------------------------------------------------------------
+//
+CVPNConnAgt::~CVPNConnAgt()
+    {
+    LOG(TName name;
+    name.AppendFormat(_L("[0x%08x]"), this);
+    Log::Printf(_L("%s Destructing VPN Connection Agent\n"),name.PtrZ()));
+
+    iEventMediator.Close();
+    
+    iServiceStartedCallback.Cancel();
+    iConnectCompleteCallback.Cancel();
+    iDisconnectCallback.Cancel();
+
+    delete iAD;
+    }
+
+// ---------------------------------------------------------------------------
+// NewL() 
+// ---------------------------------------------------------------------------
+//
+CVPNConnAgt* CVPNConnAgt::NewL()
+    {
+    CVPNConnAgt* self = new (ELeave) CVPNConnAgt();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// ConstructL() 
+// ---------------------------------------------------------------------------
+//
+inline void CVPNConnAgt::ConstructL()
+    {
+    LOG_1("[0x%08x] Constructing VPN Connection Agent\n", this);
+    // construct the database and dialog processor
+    CAgentBase::ConstructL();
+    iConnected = EFalse;
+    iDisconnecting = EFalse;
+    LOG_("CVPNConnAgt::ReadConfigurationL EventMediator");
+    User::LeaveIfError(iEventMediator.Connect());
+
+    iAD = CAsyncDisconnecter::NewL(this);  
+    }
+
+// ---------------------------------------------------------------------------
+// Info() 
+// ---------------------------------------------------------------------------
+//
+void CVPNConnAgt::Info(
+    TNifAgentInfo& aInfo) const
+    {
+    aInfo.iName = KVPNConnAgtName;
+    aInfo.iName.AppendFormat(_L("-AgentFactory[0x%08x]"), this);
+    aInfo.iVersion = TVersion(
+        TCommDbConnPref::KMajorVersionNumber,
+        TCommDbConnPref::KMinorVersionNumber,
+        TCommDbConnPref::KBuildVersionNumber
+    );
+    }
+
+// ---------------------------------------------------------------------------
+// Connect() 
+// ---------------------------------------------------------------------------
+//
+void CVPNConnAgt::Connect(
+    TAgentConnectType /*aType*/)
+    {
+    iServiceStartedCallback.CallBack();
+    }
+
+// ---------------------------------------------------------------------------
+// Connect() 
+// ---------------------------------------------------------------------------
+//
+void CVPNConnAgt::Connect(
+    TAgentConnectType   aType, 
+    CStoreableOverrideSettings* /*aOverrideSettings*/)
+    {
+    Connect(aType);
+    }
+
+// ---------------------------------------------------------------------------
+// CancelConnect() 
+// ---------------------------------------------------------------------------
+//
+void CVPNConnAgt::CancelConnect()
+    {
+    LOG_("CVPNConnAgt::CancelConnect");
+    iServiceStartedCallback.Cancel();
+    iConnectCompleteCallback.Cancel();
+    }
+
+// ---------------------------------------------------------------------------
+// Disconnect() 
+// ---------------------------------------------------------------------------
+//
+void CVPNConnAgt::Disconnect(
+    TInt aReason)
+    {
+    LOG_1("Disconnect called from Nifman with reason:%d\n", aReason);
+    if ( iDisconnecting )
+        {
+        LOG_("Already disconnecting, return\n");
+        return;
+        }
+    
+    if ( aReason == KErrConnectionTerminated )
+        iDisconnectType = (TDeactivateType)SILENT_DISCONNECT_MODE;
+
+    iLastErrorCode = aReason;
+    iDisconnectCallback.CallBack();
+    }
+
+    
+/****************************************************************************/
+/* GetExcessData()                                                          */
+/****************************************************************************/
+TInt CVPNConnAgt::GetExcessData(
+    TDes8& /*aBuffer*/)
+    {
+    return KErrNotSupported;
+    }
+
+/****************************************************************************/
+/* Notification()                                                           */
+/* Nif calls this via agentref to pass the name of the nif.                 */
+/****************************************************************************/
+TInt CVPNConnAgt::Notification(
+    TNifToAgentEventType aEvent,
+    TAny* aInfo)
+    {
+    if ( (TTunnelNifToAgentEventType)aEvent == ENifToAgentEventTypeSetIfName )
+        {
+        iVPNParameters.SetVPNNifName(*(TName*)aInfo);
+        return KErrNone;
+        }
+
+    if ( aEvent == ENifToAgentEventTypeLinkLayerDown )
+        {// Tunnelnif down
+        return KErrNone;
+        }
+
+    return KErrNotSupported;
+    }
+
+/****************************************************************************/
+/* GetLastError()                                                           */
+/****************************************************************************/
+void CVPNConnAgt::GetLastError(TInt& aError)
+    {
+    aError = iLastErrorCode;
+    }
+
+TInt CVPNConnAgt::IncomingConnectionReceived()
+    {
+    return KErrNotSupported;
+    }
+
+/****************************************************************************/
+/* ServiceStartedCb()                                                       */
+/****************************************************************************/
+TInt CVPNConnAgt::ServiceStartedCb(TAny* aThisPtr)
+    {
+    CVPNConnAgt* self = (CVPNConnAgt*)aThisPtr;
+
+    TInt err = KErrNone;
+    self->ServiceStarted(err);
+    return err;
+    }
+
+/****************************************************************************/
+/* ConnectCompleteCb()                                                      */
+/****************************************************************************/
+TInt CVPNConnAgt::ConnectCompleteCb(
+    TAny* aThisPtr)
+    {
+    CVPNConnAgt* self = (CVPNConnAgt*) aThisPtr;
+    self->ConnectionComplete(KErrNone);
+    return KErrNone;
+    }
+
+/****************************************************************************/
+/* DisconnectCompleteCb()                                                   */
+/****************************************************************************/
+TInt CVPNConnAgt::DisconnectCompleteCb(
+    TAny* aThisPtr)
+    {
+    CVPNConnAgt* self = (CVPNConnAgt*) aThisPtr;
+    self->DisconnectionComplete();
+    return KErrNone;
+    }
+
+/****************************************************************************/
+/* ServiceStarted()                                                         */
+/****************************************************************************/
+void CVPNConnAgt::ServiceStarted(TInt& aError)
+    {
+    iLastErrorCode = KErrNone;
+
+    iNotify->AgentProgress(EVPNConnAgtConnecting, iLastErrorCode);
+
+    // read IAP configuration
+    TRAP(iLastErrorCode, ReadConfigurationL());
+    if ( iLastErrorCode )
+        {
+        LOG(TName name;
+        name.AppendFormat(_L("[0x%08x]"), this);
+        Log::Printf(_L("%s Error %d in reading configuration\n"),name.PtrZ(), iLastErrorCode));
+
+        iNotify->ConnectComplete(iLastErrorCode);
+        aError = iLastErrorCode;
+        return;
+        }
+ 
+    LOG_1("[0x%08x] Get protocol version\n", this);
+    iProtocolVersionDes().iId = iEventMediator.NewEventSpecId();
+    iProtocolVersionDes().iPolicyId = *(iVPNParameters.GetVPNPolicy());
+    iEventMediator.ListenToEvent(
+        EGetProtocolVersionEvent, iProtocolVersionDes, *this);
+    iState = EGettingProtocolVersion;
+    }
+
+/****************************************************************************/
+/* ConnectionComplete()                                                     */
+/****************************************************************************/
+void CVPNConnAgt::ConnectionComplete(
+    TInt aError)
+    {
+    if ( aError )
+        {
+        switch ( iState )
+            {
+            case EGettingProtocolVersion:
+                iEventMediator.CancelListening(EGetProtocolVersionEvent, iProtocolVersionDes);
+                iNotify->AgentProgress(EVPNConnAgtDisconnected, aError);
+                iNotify->ConnectComplete(aError);
+                iState = EConnectionClosed;
+                return;
+            case EConnecting:
+                iEventMediator.CancelListening(EStartVpnConnEvent, iStartVpnConnDes);
+                iNotify->AgentProgress(EVPNConnAgtDisconnected, aError);
+                iNotify->ConnectComplete(aError);
+                iState = EConnectionClosed;
+                return;
+            default:
+                break;
+            }
+        return;
+        }
+
+    TInetIfConfig addr;
+    addr.iAddress = iVPNParameters.GetVPNNifAddress();
+    addr.iNameSer1 = iVPNParameters.GetVPNNifDNS1();
+    addr.iNameSer2 = iVPNParameters.GetVPNNifDNS2();
+
+    LOG(TName name;
+    name.AppendFormat(_L("[0x%08x]"), this);
+    TBuf<39> addrBuf;
+    iVPNParameters.GetVPNNifAddress().OutputWithScope(addrBuf);
+    Log::Printf(_L("%s Vpn interface address = %s\n"),name.PtrZ(), addrBuf.PtrZ()));
+
+    LOG(iVPNParameters.GetVPNNifDNS1().OutputWithScope(addrBuf);
+    Log::Printf(_L("%s Vpn DNS1 = %s\n"),name.PtrZ(), addrBuf.PtrZ()));
+
+    LOG(iVPNParameters.GetVPNNifDNS2().OutputWithScope(addrBuf);
+    Log::Printf(_L("%s Vpn DNS2 = %s\n"),name.PtrZ(), addrBuf.PtrZ()));
+
+    // Send VPN interface address to the tunnelnif
+    iNotify->Notification((TAgentToNifEventType)EAgentToNifEventTypeSetAddress, (void*)(&addr));
+
+    // Inform the Nifman
+    iNotify->AgentProgress(EVPNConnAgtConnected, KErrNone);
+    iNotify->ConnectComplete(aError); 
+
+    iConnected = ETrue;
+
+    // initialize real if observer
+    iObserveRealIapConnDes().iRealIapConnInfo.iIapId = iVPNParameters.GetRealIapId();
+    iObserveRealIapConnDes().iRealIapConnInfo.iNetId = iVPNParameters.GetRealNetworkId();
+    iObserveRealIapConnDes().iVpnIapId = iVPNParameters.GetVPNIapId();
+
+    ListenRealIAP();
+    ListenAddressChange();
+    
+    iState = EListeningEvents;
+    LOG_1("[0x%08x] VPN CONNECTION READY!\n", this);
+    }
+
+/****************************************************************************/
+/* DisconnectionComplete()                                                  */
+/****************************************************************************/
+void CVPNConnAgt::DisconnectionComplete()
+    {
+    if ( iDisconnecting )
+        {
+        LOG(TName name;
+        name.AppendFormat(_L("[0x%08x]"), this);
+        Log::Printf(_L("%s Already disconnecting, return\n"),name.PtrZ()));
+        return;
+        }
+    else
+        iDisconnecting = ETrue;
+    
+    iNotify->AgentProgress(EVPNConnAgtDisconnecting, KErrNone);
+        
+    if ( iConnected && (iState == EListeningEvents || iState == EStartingRealIf) )
+        {
+        // Start the deactivate/unload of the VPN policies.
+        CancelListeners();
+
+        if ( iState == EStartingRealIf )
+            iDisconnectType = (TDeactivateType)SILENT_DISCONNECT_MODE;
+
+        iCloseVpnConnDes().iId = iEventMediator.NewEventSpecId();
+        iCloseVpnConnDes().iIkePolicyHandle = iVPNParameters.GetIkePolicyHandle();
+        iCloseVpnConnDes().iIpsecPolicyHandle = iVPNParameters.GetIpsecPolicyHandle();
+        iCloseVpnConnDes().iDeactivateType = iDisconnectType;
+        iCloseVpnConnDes().iVpnIapId = iVPNParameters.GetVPNIapId();
+        iCloseVpnConnDes().iRealIapId = iVPNParameters.GetRealIapId();
+        iEventMediator.ListenToEvent(ECloseVpnConnEvent, iCloseVpnConnDes, *this);
+        iState = EClosingConnection;
+
+        LOG(TName name;
+        name.AppendFormat(_L("[0x%08x]"), this);
+        Log::Printf(_L("%s Disconnecting type is %d\n"),name.PtrZ(), (TInt)iDisconnectType));
+
+        return;
+        }
+
+    iAD->ConfirmDisconnect();
+    iDisconnecting = EFalse;
+    }
+
+
+/****************************************************************************/
+/* EventOccured()                                                           */
+/****************************************************************************/
+void CVPNConnAgt::EventOccured(TInt aStatus, TEventType aType, TDesC8* aData)
+    {
+    LOG(TName name;
+    name.AppendFormat(_L("[0x%08x]"), this);
+    Log::Printf(_L("%s Event occured with status %d\n"),name.PtrZ(), aStatus));
+
+    if ( aStatus == KErrServerTerminated )
+        {                
+        iNotify->Notification(EAgentToNifEventTypeDisableConnection, NULL);
+        iConnected = EFalse; // Disable listening of ECloseVpnConnEvent event 
+        return;
+        }
+    
+    if ( aStatus != KErrNone || !aData )
+        {
+        if ( !iConnected )
+            ConnectionComplete(aStatus);
+        else
+            DisconnectionComplete();
+        
+        return;
+        }
+
+    TGetProtocolVersionEventData* protocolVersion=NULL;
+    TStartVpnConnEventData* connection = NULL;
+    TCloseVpnConnEventData* closeData = NULL;
+    switch (aType)
+        {
+        case EGetProtocolVersionEvent:
+            protocolVersion = (TGetProtocolVersionEventData*)(aData->Ptr());
+            if ( protocolVersion->iTaskStatus )
+                {
+                TProtocolVersion pv(EVersionIp);
+                iVPNParameters.SetProtocolVersion(pv);
+                }
+            else          
+                iVPNParameters.SetProtocolVersion(protocolVersion->iProtocolVersion);
+                                
+                
+            LOG(Log::Printf(_L("%s Protocol resolved = %d\n"),name.PtrZ(), protocolVersion->iProtocolVersion));
+    
+            // Inform Nifman to go forward
+            iNotify->ServiceStarted();
+
+            // Initialise the connection parameters
+            iStartVpnConnDes().iId = iEventMediator.NewEventSpecId();
+            iStartVpnConnDes().iIfInfo.iVpnIapId = iVPNParameters.GetVPNIapId();
+            iStartVpnConnDes().iIfInfo.iVpnNetId = iVPNParameters.GetVPNNetworkId();
+            iStartVpnConnDes().iIfInfo.iRealIapId = iVPNParameters.GetRealIapId();
+            iStartVpnConnDes().iIfInfo.iRealNetId = iVPNParameters.GetRealNetworkId();
+            iStartVpnConnDes().iIfInfo.iVPNIfName = *(VPNNifName());
+            iStartVpnConnDes().iPolicyId = *(iVPNParameters.GetVPNPolicy());
+
+            LOG(Log::Printf(_L("%s Start connection\n"),name.PtrZ()));
+
+            // Start connection
+            iEventMediator.ListenToEvent(EStartVpnConnEvent, iStartVpnConnDes, *this);
+            iState = EConnecting;
+            break;
+        case EStartVpnConnEvent:
+            // Read the connection data (addresses and policy
+            // handles)
+            connection = (TStartVpnConnEventData*)(aData->Ptr());
+            ASSERT(connection);
+            if ( connection->iTaskStatus )
+                {
+                ConnectionComplete(connection->iTaskStatus);
+                break;
+                }
+
+            LOG(Log::Printf(_L("%s Connection started, Ikehandle: %d, Ipsechandle: %d\n"),
+                name.PtrZ(), connection->iIkePolicyHandle, connection->iIpsecPolicyHandle));
+            iVPNParameters.SetRealNetworkId(connection->iNetId); 
+            iVPNParameters.SetRealIapId(connection->iIapId); 
+            iVPNParameters.SetIkePolicyHandle(connection->iIkePolicyHandle);
+            iVPNParameters.SetIpSecPolicyHandle(connection->iIpsecPolicyHandle);
+            iVPNParameters.SetAddresses(connection->iVpnAddressInfo);
+            iState = EConnected;
+            ConnectionComplete(KErrNone);
+            break;
+        case ECloseVpnConnEvent:
+            LOG(Log::Printf(_L("%s ECloseVpnConnEvent\n"),name.PtrZ()));
+            closeData = (TCloseVpnConnEventData*)(aData->Ptr());
+            if ( closeData->iTaskStatus )
+                {
+                LOG(Log::Printf(_L("%s ECloseVpnConnEvent: TaskStatus %d\n"),name.PtrZ(), closeData->iTaskStatus));
+                iLastErrorCode = closeData->iTaskStatus;
+                }
+
+            if ( iEventActivatedClose )
+                {
+                iEventActivatedClose = EFalse;
+                iNotify->Notification(EAgentToNifEventTypeDisableConnection, NULL);
+                }
+
+            iAD->ConfirmDisconnect();
+            iDisconnecting = EFalse;
+
+            iConnected = EFalse;
+            
+            iState = EIdle;
+            break;
+        case EAllInterfaceEvents:
+        case EObserveRealIapConnEvent:
+            {
+            if ( iDisconnecting ) // Shouldn't be possible
+                break;
+            
+            LOG(Log::Printf(_L("%s Real interface down, shutdown silently\n"),name.PtrZ()));
+
+            iEventActivatedClose = ETrue;
+            iDisconnectType = (TDeactivateType)SILENT_DISCONNECT_MODE; // means that KMD doesn't send any packets to the gateway
+            DisconnectionComplete();
+            break;
+            }
+        case EKmdAddressChangeEvent:
+            {
+            LOG_1("[0x%08x] Address changed event\n",this);
+
+            TVPNAddress* ptr = (TVPNAddress*)(aData->Ptr());
+
+            if ( iVPNParameters.GetVPNNifAddress().CmpAddr(ptr->iVPNIfAddr)
+                 && iVPNParameters.GetVPNNifDNS1().CmpAddr(ptr->iVPNIfDNS1)
+                 && iVPNParameters.GetVPNNifDNS2().CmpAddr(ptr->iVPNIfDNS2) )
+                {
+                LOG_("Address change informed but no change found");
+
+                TConnectionInfo vpnIfaceInfo;
+                vpnIfaceInfo.iIapId = iVPNParameters.GetVPNIapId();
+                TConnectionInfoBuf vpnIfaceInfoBuf(vpnIfaceInfo);
+                iEventMediator.ListenToEvent(
+                    EKmdAddressChangeEvent, vpnIfaceInfoBuf, *this);
+                }
+            else
+                {
+                iVPNParameters.SetAddresses(*ptr);
+                TInetIfConfig addr;
+                addr.iAddress = iVPNParameters.GetVPNNifAddress();
+                addr.iNameSer1 = iVPNParameters.GetVPNNifDNS1();
+                addr.iNameSer2 = iVPNParameters.GetVPNNifDNS2();
+
+                iNotify->Notification(
+                    (TAgentToNifEventType)EAgentToNifEventTypeUpdateAddress,
+                    (void*)(&addr));
+
+                LOG(Log::Printf(_L("%s Address changed, continue listening\n"),name.PtrZ()));
+                
+                TConnectionInfo vpnIfaceInfo;
+                vpnIfaceInfo.iIapId = iVPNParameters.GetVPNIapId();
+                TConnectionInfoBuf vpnIfaceInfoBuf(vpnIfaceInfo);
+                iEventMediator.ListenToEvent(EKmdAddressChangeEvent, vpnIfaceInfoBuf, *this);
+
+                LOG(TBuf<39> addrBuf;
+                iVPNParameters.GetVPNNifAddress().OutputWithScope(addrBuf);
+                Log::Printf(_L("%s New Vpn interface address = %s\n"),name.PtrZ(), addrBuf.PtrZ()));
+
+                LOG(iVPNParameters.GetVPNNifDNS1().OutputWithScope(addrBuf);
+                Log::Printf(_L("%s Vpn DNS1 = %s\n"),name.PtrZ(), addrBuf.PtrZ()));
+
+                LOG(iVPNParameters.GetVPNNifDNS2().OutputWithScope(addrBuf);
+                Log::Printf(_L("%s Vpn DNS2 = %s\n"),name.PtrZ(), addrBuf.PtrZ()));
+                }
+            break;
+            }
+        default:
+            break;
+        }
+    }
+
+
+/****************************************************************************/
+/* ListenRealIAP()                                                          */
+/****************************************************************************/
+void CVPNConnAgt::ListenRealIAP()
+    {
+    // Listen the real interface if it shutsdown or...
+    iObserveRealIapConnDes().iId = iEventMediator.NewEventSpecId();
+    iEventMediator.ListenToEvent(
+        EObserveRealIapConnEvent, iObserveRealIapConnDes, *this);
+    }
+
+/****************************************************************************/
+/* ListenAddressChange()                                                    */
+/****************************************************************************/
+void CVPNConnAgt::ListenAddressChange()
+    {
+    // Listen to the VPN interface for address changes
+    TConnectionInfo vpnIfaceInfo;
+    vpnIfaceInfo.iIapId = iVPNParameters.GetVPNIapId();
+    TConnectionInfoBuf vpnIfaceInfoBuf(vpnIfaceInfo);
+    iEventMediator.ListenToEvent(
+        EKmdAddressChangeEvent, vpnIfaceInfoBuf, *this);
+    }
+
+/****************************************************************************/
+/* CancelListeners()                                                        */
+/****************************************************************************/
+void CVPNConnAgt::CancelListeners()
+    {
+    // Cancel real interface observer
+    iEventMediator.CancelListening(
+        EObserveRealIapConnEvent, iObserveRealIapConnDes);
+
+   // Cancel address change event listening
+    TConnectionInfo vpnIfaceInfo;
+    vpnIfaceInfo.iIapId = iVPNParameters.GetVPNIapId();
+    TConnectionInfoBuf vpnIfaceInfoBuf(vpnIfaceInfo);
+    iEventMediator.CancelListening(EKmdAddressChangeEvent, vpnIfaceInfoBuf);
+    }
+
+// ---------------------------------------------------------------------------
+// Overwrite version of ReadDes to catch the ip version asking
+// ---------------------------------------------------------------------------
+//
+TInt CVPNConnAgt::DoReadDes(
+    const TDesC& aField, TDes16& aValue, const RMessagePtr2* /*aMessage*/ )
+    {
+    TInt err(KErrNone);
+    LOG_1("CVPNConnAgt::DoReadDes aField=%S", &aField);
+    
+    // If SERVICE_IF_NETWORKS is asked, get the ip version from the VPN
+    // Manager Server. Otherwise use default ReadDes() function.
+    //    TBuf<KCommsDbSvrMaxColumnNameLength> columnName=TPtrC(
+    //          SERVICE_IF_NETWORKS);
+    // temporary solution
+    TBuf<KDbStoreMaxColumnLength> columnName=TPtrC(SERVICE_IF_NETWORKS);
+    if ( aField.CompareF(columnName) == 0 )
+        {
+        TProtocolVersion protocol = iVPNParameters.GetProtocolVersion();
+        if ( protocol == EVersionUnknown )
+            return KErrNotFound;
+        
+        if ( protocol == EVersionIp )
+            {
+            _LIT(KIP4, "ip");
+            aValue = KIP4;
+            }
+        else
+            {
+            _LIT(KIP6, "ip6");
+            aValue = KIP6;            
+            }
+        LOG_1("CVPNConnAgt::DoReadDes aValue=%S", &aValue);
+        return KErrNone;
+        }
+    else
+        {
+        err = iDatabase->ReadDes(aField, columnName);
+        if ( err )
+            return err;
+
+        aValue.Copy(columnName);
+        }
+    
+    LOG_1("CVPNConnAgt::DoReadDes aValue=%S", &aValue);
+    return err;
+    }
+
+// ---------------------------------------------------------------------------
+// Read IAP configurations 
+// ---------------------------------------------------------------------------
+//
+void CVPNConnAgt::ReadConfigurationL()
+    {
+    // vpn iap id    
+    LOG_1("CVPNConnAgt::ReadConfigurationL iIAPId:%d", iSettings.iIAPId);    
+    iVPNParameters.SetVPNIapId(iSettings.iIAPId);
+    
+    // read vpn connection method
+    using namespace CMManager;
+    RCmManager cmManager;    
+    cmManager.OpenL();
+    CleanupClosePushL( cmManager );      
+    RCmConnectionMethod vpnConnection = 
+        cmManager.ConnectionMethodL( iSettings.iIAPId );
+    CleanupClosePushL(vpnConnection);
+    ASSERT( vpnConnection.GetBoolAttributeL(ECmVirtual) );
+
+    // Read VPN Network Id
+    const TUint32 vpnNetworkId(vpnConnection.GetIntAttributeL(ECmNetworkId));
+    iVPNParameters.SetVPNNetworkId(vpnNetworkId);
+
+    LOG_1("CVPNConnAgt::ReadConfigurationL VpnIapId:%d", 
+        iVPNParameters.GetVPNIapId());
+    LOG_1("CVPNConnAgt::ReadConfigurationL VpnNetworkId:%d", 
+        iVPNParameters.GetVPNNetworkId());    
+        
+    // vpn policy id
+    HBufC* policy = vpnConnection.GetStringAttributeL(EVpnServicePolicy);
+    if (policy)
+        {     
+        TVpnPolicyId policyId;
+        ASSERT( policy->Length() <= policyId.MaxLength() );
+
+        policyId.Copy(*policy);
+        delete policy;
+        iVPNParameters.SetVPNPolicy(policyId);        
+        }
+    
+    // real IAP or SNAP. ECmNextLayerIapId == EVpnIapId
+    const TUint32 realIap(vpnConnection.GetIntAttributeL(EVpnIapId)); 
+    const TUint32 snap( !realIap ? 
+        vpnConnection.GetIntAttributeL(ECmNextLayerSNAPId):0);
+       
+    CleanupStack::PopAndDestroy(); // vpnConnection
+    
+    if ( realIap )
+        {        
+        // Now load real connection
+        RCmConnectionMethod realConnection = 
+            cmManager.ConnectionMethodL( realIap );
+        CleanupClosePushL(realConnection);      
+        ASSERT( !realConnection.GetBoolAttributeL(ECmVirtual) );
+        
+        // real iap id
+        const TUint32 realIapId( realConnection.GetIntAttributeL(ECmIapId) );
+        iVPNParameters.SetRealIapId( realIapId );
+        
+        // real network id
+        iVPNParameters.SetRealNetworkId(
+            realConnection.GetIntAttributeL(ECmNetworkId) );       
+        CleanupStack::PopAndDestroy(); // realConnection
+        }
+    else
+        {
+        LOG_1("CVPNConnAgt::ReadConfigurationL snap:%d", snap);
+        ASSERT( snap ); // must be snap then
+        iStartVpnConnDes().iIfInfo.iSnapId = snap;
+        }
+    CleanupStack::PopAndDestroy(); // cmManager
+    
+    LOG_1("CVPNConnAgt::ReadConfigurationL RealIap:%d", 
+        realIap);    
+    LOG_1("CVPNConnAgt::ReadConfigurationL RealIapId:%d", 
+        iVPNParameters.GetRealIapId());
+    LOG_1("CVPNConnAgt::ReadConfigurationL RealNetworkId:%d", 
+        iVPNParameters.GetRealNetworkId());
+    }
+
+
+//////////////////////CAsyncDisconnecter////////////////////
+
+// ---------------------------------------------------------------------------
+// CAsyncDisconnecter 
+// ---------------------------------------------------------------------------
+//
+CAsyncDisconnecter::CAsyncDisconnecter(
+    CVPNConnAgt* aAgent):
+    CAsyncOneShot(EPriorityNormal)
+    {
+    iAgent = aAgent;
+    }
+
+// ---------------------------------------------------------------------------
+// NewL 
+// ---------------------------------------------------------------------------
+//
+CAsyncDisconnecter* CAsyncDisconnecter::NewL(
+    CVPNConnAgt* aAgent)
+    {
+    return new (ELeave) CAsyncDisconnecter(aAgent);
+    }
+
+// ---------------------------------------------------------------------------
+// ConfirmDisconnect 
+// ---------------------------------------------------------------------------
+//
+void CAsyncDisconnecter::ConfirmDisconnect()
+    {
+    Call();
+    }
+
+// ---------------------------------------------------------------------------
+// RunL 
+// ---------------------------------------------------------------------------
+//
+void CAsyncDisconnecter::RunL()
+    {
+    LOG_1("CAsyncDisconnecter::RunL, iStatus:%d", iStatus.Int() );
+    iAgent->Notify()->AgentProgress(EVPNConnAgtDisconnected, KErrNone);
+    iAgent->Notify()->DisconnectComplete();
+    }
+