networksecurity/ipsec/ipsecpol/src/ipsecpolmanutil.cpp
changeset 0 af10295192d8
child 17 d566d76acea1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networksecurity/ipsec/ipsecpol/src/ipsecpolmanutil.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,1235 @@
+// Copyright (c) 2005-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:
+// IPSecPolManUtil.cpp - IPSec Policy Manager Utilities
+//
+
+#include <in_sock.h>
+
+#include "ipsecpolmanhandler.h"
+#include "ipsecpolparser.h"
+#include "ipsecpolapi.h"
+
+//
+// Build and write the strings to a policy file that tell that the clean
+// tunnel mode IKE negotiation packets are accepted. For each gateway
+// two strings are written: port 500 and port 4500.
+// The format of strings are shown below. 10.10.10.10%2 is in this example
+// an IPv4 gateway address, 255.255.255.255 is IPv4 full mask.
+//
+// remote 10.10.10.10%2 255.255.255.255 protocol 17 local_port  500
+// remote 10.10.10.10%2 255.255.255.255 protocol 17 local_port 4500
+//
+//
+TInt 
+CIPSecPolicyManagerHandler::WriteTunnelModeIkeNegotiationStringsL(
+    HBufC8*& aPolBfr)
+    {
+    TBuf8<1024> stringBuf;
+    TInt err(KErrNone);
+
+    // Create pointer array for gateway list
+    RPointerArray<TInetAddr> gatewayList;
+    CleanupClosePushL(gatewayList);
+
+    // Set base for the selector list
+    CSecurityPolicy* sp = iPieceData->Policies();
+    CSelectorList* selectorList = sp->SelectorList();
+    TInt selectorCount = selectorList->Count();
+
+    // Loop through the selector list
+    for (TInt i = 0; (i < selectorCount) && (err == KErrNone) ; i++)
+        {
+        CPolicySelector* policySelector = selectorList->At(i);
+        TSecpolBundleIter iterl(policySelector->iBundle);
+        CSecpolBundleItem* itemL = NULL;
+        CSecpolBundleItem* itemWork;
+       
+        // Find the last item in bundle
+        while ((itemWork = iterl++) != NULL)
+            {
+            if (!itemWork->iTunnel.IsUnspecified())
+                itemL = itemWork;
+            }
+        // Add the address of the last gateway in the bundle
+        // to the gateway list
+        if (itemL)
+            {
+            // Search a matching element from the gateway list
+            TInt count = gatewayList.Count();
+            TInt j;
+            for (j = 0; j < count && !itemL->iTunnel.Match(*gatewayList[j]); j++){}
+            // Add a new element to the gateway list
+            if (j==count)
+                {
+                TInt position = 0;
+                gatewayList.Insert( &itemL->iTunnel, position);
+
+                // Build two strings for policy file
+                stringBuf.Zero();
+                BuildTunnelModeIkeString(stringBuf,
+                                         EInbound,
+                                         500,
+                                         itemL->iTunnel);
+                BuildTunnelModeIkeString(stringBuf,
+                                         EInbound,
+                                         4500,
+                                         itemL->iTunnel);
+
+                // Write the string to file
+                err = TPolicyParser::BufferAppend(aPolBfr, stringBuf);
+                }
+            }
+        }
+
+    CleanupStack::PopAndDestroy();
+    return err;
+    }
+//
+// Build a string that tells that the clean tunnel mode IKE
+// negotiation packets are accepted:
+// remote 10.10.10.10%2 255.255.255.255 protocol 17 local_port 500
+//
+//
+void 
+CIPSecPolicyManagerHandler::BuildTunnelModeIkeString(
+    TDes8& aStringBuf,
+    TInt aDirection,
+    TInt aPort,
+    TInetAddr& aGwAddr)
+    {
+    TBuf<60> addr;
+
+    // Gateway IP address
+    aStringBuf.Append(_L8(" remote "));
+    aGwAddr.OutputWithScope(addr);
+    aStringBuf.Append(addr);
+
+    // Full mask, either IPv4 or IPv6
+    if (aGwAddr.Family() == KAfInet || aGwAddr.IsV4Mapped())
+        {
+        if (!aGwAddr.Scope())
+            {
+            aStringBuf.Append(_L8(" 255.255.255.255 "));
+            }
+        else
+            {
+            aStringBuf.Append(_L8(" 255.255.255.255%-1 "));
+            }
+        }
+    else
+        {
+        aStringBuf.Append(_L8(" FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF "));
+        }
+
+    // Protocol UDP
+    aStringBuf.Append(_L8(" protocol 17 "));
+
+    // Local or remote port
+    if (aDirection == EInbound)
+        {
+        aStringBuf.Append(_L8(" local_port "));
+        }
+    else
+        {
+        aStringBuf.Append(_L8(" remote_port "));
+        }
+
+    // Port number
+    aStringBuf.AppendFormat(_L8(" %d = { }\n"), aPort);
+    }
+
+//
+// Build and write the strings to a policy file that tell that the clean
+// transport mode IKE negotiation packets are accepted. For each
+// transport mode selector two strings are written: port 500 and port 4500.
+// The format of strings are shown below. 10.10.10.10%2 is in this example
+// an IPv4 transport mode net, 255.255.255.0 is an IPv4 net mask.
+//
+// remote 10.10.10.10%2 255.255.255.0%-1 protocol UDP local_port  500
+// remote 10.10.10.10%2 255.255.255.0%-1 protocol UDP local_port 4500
+//
+//
+TInt 
+CIPSecPolicyManagerHandler::WriteTransportModeIkeNegotiationStrings(
+    HBufC8*& aPolBfr)
+    {
+    TInt err = KErrNone;
+
+    //  Set base for the selector list
+    CSecurityPolicy* sp = iPieceData->Policies();
+    CSelectorList* selectorList = sp->SelectorList();
+    TInt selectorCount = selectorList->Count();
+
+    // Loop through the selector list
+    for (TInt i = 0; i < selectorCount; i++)
+        {
+        CPolicySelector* policySelector = selectorList->At(i);
+        if (policySelector->iBundle.IsEmpty())
+            {
+            continue;
+            }
+        TSecpolBundleIter iterl(policySelector->iBundle);
+        CSecpolBundleItem* itemFirst = iterl;
+
+        // Calculate the bundle count
+        TInt bundleCount = 0;
+        while ((iterl++) != NULL)
+            {
+            bundleCount++;
+            }
+
+        // Check that no gateway is specified, it means transport mode
+        if (bundleCount == 1
+            && itemFirst != NULL
+            && itemFirst->iTunnel.IsUnspecified())
+            {
+            // Build two strings for policy file
+            TBuf8<1024> stringBuf;
+            stringBuf.Zero();
+            BuildTransportModeIkeString(stringBuf,
+                                        500,
+                                        policySelector->iRemote,
+                                        policySelector->iRemoteMask);
+            BuildTransportModeIkeString(stringBuf,
+                                        4500,
+                                        policySelector->iRemote,
+                                        policySelector->iRemoteMask);
+            // Write the string to file
+            err = TPolicyParser::BufferAppend(aPolBfr, stringBuf);
+            }
+        if (err != KErrNone)
+            {
+            break;
+            }
+        }
+    return err;
+    }
+
+//
+// Build a string that tells that the clean Transport mode IKE
+// negotiation packets are accepted:
+// remote 10.10.10.10%2 255.255.255.255%-1 protocol UDP local_port 500
+//
+//
+void 
+CIPSecPolicyManagerHandler::BuildTransportModeIkeString(
+    TDes8& aStringBuf,
+    TInt aPort,
+    TInetAddr& aRemote,
+    TInetAddr& aRemoteMask)
+    {
+    TBuf<60> addr;
+
+    // Gateway IP address
+    aStringBuf.Append(_L8(" remote "));
+    aRemote.OutputWithScope(addr);
+    aStringBuf.Append(addr);
+    aStringBuf.Append(_L8(" "));
+
+    // Mask
+    aRemoteMask.OutputWithScope(addr);
+    aStringBuf.Append(addr);
+    aStringBuf.Append(_L8(" "));
+
+    // Protocol UDP, local_port #, bypass action 
+    aStringBuf.AppendFormat(_L8("protocol 17 local_port %d = { }\n"), aPort);
+    }
+
+//
+// Build a string that tells that the clean DHCP protocol
+// packets are accepted:
+// outbound protocol 17 remote_port 67
+// inbound  protocol 17 local_port 68
+//
+//
+TInt 
+CIPSecPolicyManagerHandler::BuildDhcpProtocolString( HBufC8*& aPolBfr)
+    {
+    TInt err = KErrNone;
+    TBuf8<1024> stringBuf;
+
+    // Outbound, protocol UDP, remote_port 67
+    stringBuf.Append(_L8(" outbound protocol 17 remote_port 67 = { }\n"));
+
+    // Inbound, protocol UDP, local_port 68
+    stringBuf.Append(_L8(" inbound protocol 17 local_port 68 = { }\n"));
+
+    // Write the string to file
+    err = TPolicyParser::BufferAppend(aPolBfr, stringBuf);
+    return err;
+    }
+
+//
+// Build the strings that tell that clean MIPv4 protocol packets
+// are accepted:
+//
+// *** outbound solicitation messages ***
+// outbound remote 255.255.255.255 255.255 255.255 icmp_type 10
+// outbound remote 224.0.0.2       255.255.255.255 icmp_type 10
+//
+// *** outbound Registration Request message ***
+// outbound protocol 17 remote_port 434
+//
+// *** inbound Advertisement messages ***
+// inbound local 255.255.255.255 255.255.255.255 icmp_type 9
+// inbound local 224.0.0.1       255.255.255.255 icmp_type 9
+//
+// *** inbound Registration Reply message ***
+// inbound protocol 17 local_port 434
+//
+//
+TInt 
+CIPSecPolicyManagerHandler::BuildMip4BypassSelectors( HBufC8*& aPolBfr)
+    {
+    TInt err = KErrNone;
+    TBuf8<1024> stringBuf;
+
+    // Outbound Solicitation message
+    stringBuf.Append(_L8(" outbound "));
+    stringBuf.Append(_L8(" remote "));
+    stringBuf.Append(_L8(" 255.255.255.255 "));  // IP address
+    stringBuf.Append(_L8(" 255.255.255.255 "));  // Mask
+    stringBuf.Append(_L8(" icmp_type 10 = { }\n"));
+
+    // Outbound Solicitation message
+    stringBuf.Append(_L8(" outbound "));
+    stringBuf.Append(_L8(" remote "));
+    stringBuf.Append(_L8(" 224.0.0.2 "));
+    stringBuf.Append(_L8(" 255.255.255.255 "));
+    stringBuf.Append(_L8(" icmp_type 10 = { }\n"));
+
+    // Outbound Registration Request message
+    stringBuf.Append(_L8(" outbound "));
+    stringBuf.Append(_L8(" protocol 17 "));
+    stringBuf.Append(_L8(" remote_port 434 = { }\n"));
+
+    // Inbound Advertisement message
+    stringBuf.Append(_L8(" inbound "));
+    stringBuf.Append(_L8(" local "));
+    stringBuf.Append(_L8(" 255.255.255.255 "));
+    stringBuf.Append(_L8(" 255.255.255.255 "));
+    stringBuf.Append(_L8(" icmp_type 9 = { }\n"));
+
+    // Inbound Advertisement message
+    stringBuf.Append(_L8(" inbound "));
+    stringBuf.Append(_L8(" local "));
+    stringBuf.Append(_L8(" 224.0.0.1 "));
+    stringBuf.Append(_L8(" 255.255.255.255 "));
+    stringBuf.Append(_L8(" icmp_type 9 = { }\n"));
+
+    // Inbound Registration Reply message
+    stringBuf.Append(_L8(" inbound "));
+    stringBuf.Append(_L8(" protocol 17 "));
+    stringBuf.Append(_L8(" local_port 434 = { }\n"));
+
+    // Write the string to file
+    err = TPolicyParser::BufferAppend(aPolBfr, stringBuf);
+    return err;
+    }
+
+//
+//  Modify the SA names (SA = Security association) by appending
+//  the SA name with suffix ZZ_n, where the n is the next policy
+//  handle and zz_ is a separator
+//
+void 
+CIPSecPolicyManagerHandler::MakeUniqueSANamesL()
+    {
+    CSecurityPolicy* policy = iPieceData->Policies();
+    CArrayFixFlat<CPolicySpec *>* saList = policy->SAList();
+
+    // Loop here until all SPDB SA names changed
+    TInt i;
+    TBuf8<100> buf;
+    for (i = 0; i < saList->Count(); i++)
+        {
+        if (saList->At(i)->iSpectype == EPolSpecEP)
+            {
+            // TODO: Verify also that EndPoint names are unique
+            continue;
+            }
+
+        // Copy an SA name to buf
+        buf.Copy(saList->At(i)->iName->Des());
+        buf.AppendFormat(_L8("zz_%d"), iCurrentPolicyHandle.iHandle + 1);
+        // Delete the name bfr
+        delete saList->At(i)->iName;
+        saList->At(i)->iName = NULL;
+        // Allocate a new bfr
+        saList->At(i)->iName = HBufC8::NewL(buf.Length());
+        // Set the new name buffer
+        saList->At(i)->iName->Des().Copy(buf);
+        }
+    }
+
+//
+//  This function examines all selectors in the selector list and
+//  creates for each selector a comparison word that is needed
+//  to define the sequence of selectors in the file that is
+//  sent to the IPSec protocol component. The comparison word
+//  consists of the following parts:
+//  -- byte 1 = 0
+//  -- byte 2, bit 0 = 1 = port 500 or 4500 is defined in selector
+//  -- byte 2, bit 0 = 1 = port 67 and 68 is defined in selector
+//  -- byte 2, bit 0 = 1 = MIPv4 is defined by the selector
+//  -- byte 2, bit 1 = 0
+//  -- byte 4, bit 8 = 1 = all selectors have this bit on
+//
+//  The selector that has the greatest comparison word, is the first
+//  in the sequence.
+//
+TInt 
+CIPSecPolicyManagerHandler::BuildComparisonWord(CSelectorList* aSelList)
+    {
+    TInt count = aSelList->Count();
+    TInt compWord(0);
+
+    // Loop through the selector list
+    for (TInt i = 0; i < count; i++)
+        {
+        CPolicySelector* policySelector = aSelList->At(i);
+        compWord = 0;
+
+        // Check if the local port 500 or 4500 is defined in selector, or
+        // remote port 67 and local port 68 is defined, set a bit
+        // in comparison word (IKE negotiation ports or DHCP ports)
+        if ((policySelector->iLocal.Port() == 500
+             || policySelector->iLocal.Port() == 4500)
+            || (policySelector->iRemote.Port() == 67
+                && policySelector->iLocal.Port() == 68))
+            {
+            compWord |= 0x00400000;
+            }
+
+        // Check if MIP4 protocol selectors:
+        // -- IcmpType is 9 or 10
+        //    or
+        // -- iType is 9 or 10
+        //    or
+        //    protocol is 17 (UDP) and local port or remote_port is 434
+        // and set a bit in comparison word
+        if ((policySelector->iIcmpType == 9 || policySelector->iIcmpType == 10)
+            || (policySelector->iType == 9 || policySelector->iType == 10)
+            || (policySelector->iProtocol == 17
+                && (policySelector->iRemote.Port() == 434
+                    || policySelector->iLocal.Port() == 434)))
+            {
+            compWord |= 0x00400000;
+            }
+
+        // Each selector has at least this bit set on
+        compWord |= 0x00000001;
+
+        // Store comparison word to the selector
+        policySelector->iCompWord = compWord;
+        }
+
+    return (KErrNone);
+    }
+
+//
+//  This function examines all selectors in the selector list and
+//  sets a unique sequence number to each selector. The sequence
+//  numbers are used to define the sequence of selectors in a
+//  file that is sent to the IPSec protocol component.
+//  Each selector has a comparison word created previously.
+//
+//
+TInt 
+CIPSecPolicyManagerHandler::SetSequenceNumbers(CSelectorList* aSelList)
+    {
+    TInt count = aSelList->Count();
+    TBool complete = EFalse;
+    TInt currentSequenceNumber = 1;
+    TUint32 currentHighValue;
+    TInt j = 0;
+
+    // Loop until each selector has a sequence number (exception:
+    // ffffffff means deleted
+    while (!complete)
+        {
+        currentHighValue = 0;
+
+        // Loop through the selector list and search the selector that has
+        // the highest value in comparison field
+        for (TInt i = 0; i < count; i++)
+            {
+            CPolicySelector *policySelector = aSelList->At(i);
+
+            if (policySelector->iSequenceNumber == -1)
+                {
+                continue;
+                }
+
+            if (policySelector->iSequenceNumber == 0 &&
+                policySelector->iCompWord > currentHighValue )
+                {
+                j = i;
+                currentHighValue = policySelector->iCompWord;
+                }
+            }
+
+        // A round is complete
+        if (currentHighValue == 0)
+            {
+            complete = ETrue;  // Each selector has a sequence number
+            }
+        else
+            {
+            CPolicySelector* tempSelector = aSelList->At(j);
+            tempSelector->iSequenceNumber = currentSequenceNumber;
+            currentSequenceNumber++;
+            }
+        }
+    return 0;
+    }
+
+//
+//  Compute either IPv4 or IPv6 mask length from a mask in TInetAddr
+//
+//
+//
+TInt 
+CIPSecPolicyManagerHandler::CalculateMaskLength(TInetAddr& aMask)
+    {
+    TInt maskLength(0);
+    if (aMask.Family() == KAfInet)
+        {
+        // 96 = corresponds now IPv6 size
+        maskLength = 96 + MaskLength(aMask.Address());
+        }
+    else if (aMask.Family() == KAfInet6)
+        {
+        maskLength = MaskLength(aMask.Ip6Address());
+        }
+    return (maskLength);
+    }
+
+//
+// MaskLength
+// **********
+// Borrowed from Tcpip6\src\iface.cpp
+// Local utility, compute consecutive leftmost 1-bits from 32 bit integer
+//
+//
+TInt 
+CIPSecPolicyManagerHandler::MaskLength(TUint32 aAddr)
+    {
+    TInt count = 0;
+    while (aAddr & 0x80000000)
+        {
+        count++;
+        aAddr <<= 1;
+        }
+    return count;
+    }
+
+//
+// MaskLength
+// **********
+// Borrowed from Tcpip6\src\iface.cpp
+// Computes mask length from IPv6 address
+//
+//
+TInt 
+CIPSecPolicyManagerHandler::MaskLength(const TIp6Addr &aAddr)
+    {
+    TInt count = 0;
+    TInt len = (sizeof(aAddr.u.iAddr8) / sizeof(aAddr.u.iAddr8[0]));
+    for (TUint i = 0; i < len; ++i)
+        {
+        if (aAddr.u.iAddr8[i] == 0xFF)
+            {
+            count += 8;
+            }
+        else
+            {
+            // Calls 32-bit routine
+            count += MaskLength(aAddr.u.iAddr8[i] << 24);
+            break;
+            }
+        }
+    return count;
+    }
+
+//
+// This function deletes from the policy the Inbound/Outbound
+// selector pairs by marking the selectors.
+//
+//
+void 
+CIPSecPolicyManagerHandler::DeleteExtraInboundOutboundSelectors()
+    {
+    // Set the base for the selector list
+    CSecurityPolicy* sp = iPieceData->Policies();
+    CSelectorList* list = sp->SelectorList();
+    TInt count = list->Count();
+
+    // Search a 'bypass/drop_everything_else' selectors and mark them.
+    // These selectors will be deleted later when the objects are
+    // converted to string format
+    for (TInt i = 0; i < count; i++)
+        {
+        CPolicySelector* ps = list->At(i);
+
+        if (IsBypassEverythingElse(*ps) || IsDropEverythingElse(*ps))
+            {
+            ps->iSequenceNumber = 0xffffffff;
+            }
+        }
+    }
+
+//
+// This function adds the following selectors to the end of the
+// string format policy file:
+//  inbound = { }
+//  outbound = { }
+//
+// This occurs only if the current policies are in bypass mode.
+// Bypass mode means that the packets that do not match with any other
+// selector, are transferred without IPSec encapsulation.
+//
+//
+TInt 
+CIPSecPolicyManagerHandler::AddInboundOutboundSelectorPair()
+    {
+    TBuf8<128> stringBuf;
+    TInt err(KErrNone);
+
+    // If drop mode, return immediately
+    if (iBypassOrDropMode == KDropMode)
+        {
+        return err;
+        }
+
+    // Add strings to work buffer
+    if (iBypassOrDropMode & KInboundBypass)
+        {
+        stringBuf.Append(_L8(" inbound = { }\n"));
+        }
+    if (iBypassOrDropMode & KOutboundBypass)
+        {
+        stringBuf.Append(_L8(" outbound = { }\n"));
+        }
+
+    // Write the string to file
+    err = TPolicyParser::BufferAppend(iPolBfr, stringBuf);
+    return err;
+    }
+
+//
+//  Find selector that matches with parameters given by a Key
+//  Management application. This function is a part of
+//  GetIPSecSAInfo API.
+//
+//
+CPolicySelector*
+CIPSecPolicyManagerHandler::FindMatchingSelector()
+    {
+    TInetAddr localAddr;
+    TInetAddr remoteAddr;
+
+    // Set the base for the selector list
+    CSecurityPolicy* sp = iPieceData->Policies();
+    CSelectorList* selectorList = sp->SelectorList();
+    TInt selectorCount = selectorList->Count();
+
+    // Build local subnetwork address if the mask defined
+    if (!iSelectorInfo->iLocalMask.IsUnspecified())
+        {
+        if ((iSelectorInfo->iLocal.IsV4Mapped()) &&
+            (!iSelectorInfo->iLocalMask.IsV4Mapped()))
+            {
+            iSelectorInfo->iLocalMask.ConvertToV4Mapped();
+            }
+        localAddr.SubNet(iSelectorInfo->iLocal, iSelectorInfo->iLocalMask);
+        }
+    else
+        {
+        // No mask, use host address
+        localAddr = iSelectorInfo->iLocal;   
+        }
+        
+    // Set scope too    
+    localAddr.SetScope(iSelectorInfo->iLocal.Scope());  
+
+    // Build remote subnetwork address if the mask defined
+    if (!iSelectorInfo->iRemoteMask.IsUnspecified())
+        {
+        if ((iSelectorInfo->iRemote.IsV4Mapped()) &&
+            (!iSelectorInfo->iRemoteMask.IsV4Mapped()))
+            {
+            iSelectorInfo->iRemoteMask.ConvertToV4Mapped();
+            }
+        remoteAddr.SubNet(iSelectorInfo->iRemote, iSelectorInfo->iRemoteMask);
+        }
+    else
+        {
+        // No mask, use host address
+        remoteAddr = iSelectorInfo->iRemote;
+        }
+
+    // Set scope too
+    remoteAddr.SetScope(iSelectorInfo->iRemote.Scope());
+
+    // Find the matching selector
+    for (TInt i = 0; i < selectorCount; i++)
+        {
+        CPolicySelector* policySelector = selectorList->At(i);
+        TInetAddr polLocalMask = policySelector->iLocalMask;
+        TInetAddr polRemoteMask = policySelector->iRemoteMask;
+
+        // Skip 'bypass/drop_everything_else' or interface selectors
+        if (IsBypassEverythingElse(*policySelector)
+            || IsDropEverythingElse(*policySelector)
+            || policySelector->iDirection == KPolicySelector_INTERFACE)
+            {
+            continue;
+            }
+
+        // Convert local mask of policy to V4Mapped
+        if (policySelector->iLocal.IsV4Mapped() && !polLocalMask.IsV4Mapped())
+            {
+            polLocalMask.ConvertToV4Mapped();
+            }
+
+        // Convert remote mask of policy to V4Mapped
+        if (policySelector->iRemote.IsV4Mapped() && !polRemoteMask.IsV4Mapped())
+            {
+            polRemoteMask.ConvertToV4Mapped();
+            }
+
+        // Check that protocol match if it is set
+        if ((policySelector->iProtocol) && (iSelectorInfo->iProtocol))
+            {
+            if (policySelector->iProtocol != iSelectorInfo->iProtocol)
+                {
+                continue;
+                }
+            }
+            
+        // Check that scope match if selector is 'scoped' ie. not global 
+        if (!policySelector->iGlobalSelector)
+            {
+            if ((policySelector->iLocal.Scope() != localAddr.Scope())
+                || (policySelector->iRemote.Scope() != remoteAddr.Scope()))
+                {
+                continue;
+                }
+            }
+
+        // Check that local address/port match if address/port is set
+        if (!policySelector->iLocal.IsUnspecified())
+            {
+            if (!policySelector->iLocal.Match(localAddr, polLocalMask)
+                || !policySelector->iLocal.CmpPort(iSelectorInfo->iLocal))
+                {
+                continue;
+                }
+            }
+
+        // Check that remote address/port match if address/port is set
+        if (!policySelector->iRemote.IsUnspecified())
+            {
+            if (!policySelector->iRemote.Match(remoteAddr, polRemoteMask)
+                || !policySelector->iRemote.CmpPort(iSelectorInfo->iRemote))
+                {
+                continue;
+                }
+            }
+
+        // Matching selector found so return it            
+        return (policySelector);
+        }
+
+    return (NULL);
+    }
+
+//
+// CIPSecPolicyManagerHandler::FillSAInfoObject()
+//
+// Store SA parameters from TSecurityAssocSpec object to TIPSecSAInfo object. 
+// The Info object will be delivered to the Key Management application. 
+// The function is a part of the GetIPSecSAInfo API.
+//
+//
+void 
+CIPSecPolicyManagerHandler::FillSAInfoObject(
+    CPolicySelector* aPolicySelector,
+    TInt aIndex)
+    {
+    // Clear SA Transfrom template strings
+    iSAInfo->iName.FillZ(KMaxName);
+    iSAInfo->iName.SetLength(0);
+    iSAInfo->iRemoteIdentity.FillZ(TIpsecSaSpec::KIpsecMaxIdentityLength);
+    iSAInfo->iRemoteIdentity.SetLength(0);
+    iSAInfo->iLocalIdentity.FillZ(TIpsecSaSpec::KIpsecMaxIdentityLength);
+    iSAInfo->iLocalIdentity.SetLength(0);
+
+    // Reset 'more SA exists' to default (none)
+    iSAInfo->iMoreSasExist = EFalse;
+ 
+    // Iterate through the action bundles to find the SA Transform template
+    // that corresponds with the given index
+    TSecpolBundleIter iter(aPolicySelector->iBundle);
+    TInt count(0);
+    while (iter)
+        {
+        CSecpolBundleItem* item = iter++;
+
+        if (aIndex != count)
+            {
+            count++;
+            continue;
+            }
+
+        // Corresponding bundle item found so use it to fill 
+        // SA transform template
+        
+        TBool isLast = (!iter ? ETrue : EFalse);
+        TBool isTunnelMode = (!item->iTunnel.IsUnspecified() || item->iTunnelEpName);
+
+        iSAInfo->iTransportMode = !isTunnelMode;
+        iSAInfo->iMoreSasExist = !isLast;
+
+        // Check that SA specification exists
+        
+        //
+        // NOTE:
+        //  There is a kludge for testing the plain tunnel ie. there exists 
+        //  no SA specification at all. The selector definition in the policy 
+        //  is like:
+        //
+        //      remote 192.168.1.11 255.255.255.0 = { tunnel(10.66.77.1) }
+        //
+        //  and no SA definition exist that is named as 'tunnel'
+        //
+        if (item->iSpec)
+            {
+            TSecurityAssocSpec& spec = item->iSpec->iSpec;
+            
+#ifdef SYMBIAN_IPSEC_VOIP_SUPPORT
+       	    iSAInfo->iType = item->iSpec->iPropList->At(0)->iType;
+            iSAInfo->iAalg = item->iSpec->iPropList->At(0)->iAalg;
+            iSAInfo->iAalgLen = item->iSpec->iPropList->At(0)->iAalgLen;
+            iSAInfo->iEalg = item->iSpec->iPropList->At(0)->iEalg;
+            iSAInfo->iEalgLen = item->iSpec->iPropList->At(0)->iEalgLen;
+            iSAInfo->iReplayWindowLength = spec.iReplayWindowLength;
+            iSAInfo->iPfs = spec.iPfs;
+
+	
+			iSAInfo->iHard.iBytes = item->iSpec->iPropList->At(0)->iHard.sadb_lifetime_bytes;
+            iSAInfo->iHard.iAddTime = item->iSpec->iPropList->At(0)->iHard.sadb_lifetime_addtime;
+            iSAInfo->iHard.iUseTime = item->iSpec->iPropList->At(0)->iHard.sadb_lifetime_usetime;
+
+            iSAInfo->iSoft.iAllocations = item->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_allocations;
+            iSAInfo->iSoft.iBytes = item->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_bytes;
+            iSAInfo->iSoft.iAddTime = item->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_addtime;
+            iSAInfo->iSoft.iUseTime = item->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_usetime;
+#else
+            iSAInfo->iType = spec.iType;
+            iSAInfo->iAalg = spec.iAalg;
+            iSAInfo->iAalgLen = spec.iAalgLen;
+            iSAInfo->iEalg = spec.iEalg;
+            iSAInfo->iEalgLen = spec.iEalgLen;
+            iSAInfo->iReplayWindowLength = spec.iReplayWindowLength;
+            iSAInfo->iPfs = spec.iPfs;
+
+            iSAInfo->iHard.iAllocations = spec.iHard.sadb_lifetime_allocations;
+            iSAInfo->iHard.iBytes = spec.iHard.sadb_lifetime_bytes;
+            iSAInfo->iHard.iAddTime = spec.iHard.sadb_lifetime_addtime;
+            iSAInfo->iHard.iUseTime = spec.iHard.sadb_lifetime_usetime;
+
+            iSAInfo->iSoft.iAllocations = spec.iSoft.sadb_lifetime_allocations;
+            iSAInfo->iSoft.iBytes = spec.iSoft.sadb_lifetime_bytes;
+            iSAInfo->iSoft.iAddTime = spec.iSoft.sadb_lifetime_addtime;
+            iSAInfo->iSoft.iUseTime = spec.iSoft.sadb_lifetime_usetime;
+
+#endif //SYMBIAN_IPSEC_VOIP_SUPPORT
+
+			iSAInfo->iSrcSpecific = spec.iMatchSrc;
+
+            if (item->iSpec->iName)
+                {
+                TInt len(item->iSpec->iName->Length());
+                if (len < KMaxName)
+                    {
+                    iSAInfo->iName.Copy(*item->iSpec->iName);
+                    }
+                }
+
+            if (item->iSpec->iRemoteIdentity)
+                {
+                TInt len(item->iSpec->iRemoteIdentity->Length());
+                if (len < TIpsecSaSpec::KIpsecMaxIdentityLength)
+                    {
+                    iSAInfo->iRemoteIdentity.Copy(*item->iSpec->iRemoteIdentity);
+                    }
+                }
+
+            if (item->iSpec->iLocalIdentity)
+                {
+                TInt len(item->iSpec->iLocalIdentity->Length());
+                if (len < TIpsecSaSpec::KIpsecMaxIdentityLength)
+                    {
+                    iSAInfo->iLocalIdentity.Copy(*item->iSpec->iLocalIdentity);
+                    }
+                }
+            }
+
+        break;
+        }
+    }
+
+//
+// Returns TRUE if selector is of type 'bypass_everything_else'
+// TODO:
+//  This method should be included within CPolicySelector class
+//
+//
+TBool
+CIPSecPolicyManagerHandler::IsBypassEverythingElse(
+    const CPolicySelector& aPolicySelector) const
+    {
+    return (aPolicySelector.iDirection != KPolicySelector_INTERFACE 
+            && aPolicySelector.iRemote.Family() == KAFUnspec
+            && aPolicySelector.iLocal.Family() == KAFUnspec
+            && aPolicySelector.iRemote.Port() == 0
+            && aPolicySelector.iLocal.Port() == 0
+            && aPolicySelector.iProtocol == 0
+            && aPolicySelector.iIcmpType < 0
+            && aPolicySelector.iIcmpCode < 0
+            && aPolicySelector.iType < 0
+            && aPolicySelector.iBundle.IsEmpty()
+            && !aPolicySelector.iDropAction);
+    }
+
+//
+// Returns TRUE if selector is of type 'drop_everything_else'
+// TODO:
+//  This method should be included within CPolicySelector class
+//
+//
+TBool
+CIPSecPolicyManagerHandler::IsDropEverythingElse(
+    const CPolicySelector& aPolicySelector) const
+    {
+    return (aPolicySelector.iDirection != KPolicySelector_INTERFACE
+            && aPolicySelector.iRemote.Family() == KAFUnspec
+            && aPolicySelector.iLocal.Family() == KAFUnspec
+            && aPolicySelector.iRemote.Port() == 0
+            && aPolicySelector.iLocal.Port() == 0
+            && aPolicySelector.iProtocol == 0
+            && aPolicySelector.iIcmpType < 0
+            && aPolicySelector.iIcmpCode < 0
+            && aPolicySelector.iType < 0
+            && aPolicySelector.iBundle.IsEmpty()
+            && aPolicySelector.iDropAction);
+    }
+
+//
+// Returns TRUE if given selectors are of 'interface' type and the
+// name of interfaces are equal.
+// TODO:
+//  This method should be included within CPolicySelector class
+//
+//
+TBool
+CIPSecPolicyManagerHandler::IsEqualInterface(
+    const CPolicySelector& aP1, 
+    const CPolicySelector& aP2) const
+    {
+    return ((aP1.iDirection == KPolicySelector_INTERFACE)
+            && (aP2.iDirection == KPolicySelector_INTERFACE)
+            && (aP1.iInterface == aP2.iInterface));
+    }
+
+//
+// Returns TRUE if the remote address of given selectors are equal.
+// TODO:
+//  This method should be included within CPolicySelector class
+//
+//
+TBool
+CIPSecPolicyManagerHandler::IsEqualRemoteAddress(
+    const CPolicySelector& aP1, 
+    const CPolicySelector& aP2) const
+    {
+    // Check if both addresses are set
+    if ((aP1.iRemote.Family() == KAFUnspec) 
+        || (aP2.iRemote.Family() == KAFUnspec))
+        {
+        return (EFalse);
+        }
+
+    // Check that both selectors are either global or scoped
+    if (aP1.iGlobalSelector != aP2.iGlobalSelector)
+        {
+        return (EFalse);
+        }
+    
+    // Check for address any and equal scope
+    if (aP1.iRemote.IsUnspecified() && aP2.iRemote.IsUnspecified())
+        {
+        if (aP1.iGlobalSelector && aP2.iGlobalSelector)
+            {
+            return (ETrue);
+            }
+        if (aP1.iRemote.Scope() == aP2.iRemote.Scope())
+            {
+            return (ETrue);
+            }
+        }
+        
+    // Check for specific address and equal scope
+    if ((!aP1.iRemote.IsUnspecified() && !aP2.iRemote.IsUnspecified())
+        && aP1.iRemote.Match(aP2.iRemote)
+        && aP1.iRemoteMask.Match(aP2.iRemoteMask))
+        {
+        if (aP1.iGlobalSelector && aP2.iGlobalSelector)
+            {
+            return (ETrue);
+            }
+        if (aP1.iRemote.Scope() == aP2.iRemote.Scope())
+            {
+            return (ETrue);
+            }
+        }
+        
+    return (EFalse);
+    }
+
+//
+// Returns TRUE if local address of given selectors are equal.
+// TODO:
+//  This method should be included within CPolicySelector class
+//
+//
+TBool
+CIPSecPolicyManagerHandler::IsEqualLocalAddress(
+    const CPolicySelector& aP1, 
+    const CPolicySelector& aP2) const
+    {
+    // Check that address is set
+    if ((aP1.iLocal.Family() == KAFUnspec) 
+        || (aP2.iLocal.Family() == KAFUnspec))
+        {
+        return (EFalse);
+        }
+
+    // Check that both selectors are either global or scoped
+    if (aP1.iGlobalSelector != aP2.iGlobalSelector)
+        {
+        return (EFalse);
+        }
+    
+    // Check for address any and equal scope
+    if (aP1.iLocal.IsUnspecified() && aP2.iLocal.IsUnspecified())
+        {
+        if (aP1.iGlobalSelector && aP2.iGlobalSelector)
+            {
+            return (ETrue);
+            }
+        if (aP1.iLocal.Scope() == aP2.iLocal.Scope())
+            {
+            return (ETrue);
+            }
+        }
+        
+    // Check for specific address and equal scope
+    if ((!aP1.iLocal.IsUnspecified() && !aP2.iLocal.IsUnspecified())
+        && aP1.iLocal.Match(aP2.iLocal)
+        && aP1.iLocalMask.Match(aP2.iLocalMask))
+        {
+        if (aP1.iGlobalSelector && aP2.iGlobalSelector)
+            {
+            return (ETrue);
+            }
+        if (aP1.iLocal.Scope() == aP2.iLocal.Scope())
+            {
+            return (ETrue);
+            }
+        }
+        
+    return (EFalse);
+    }
+
+//
+// Returns TRUE if given SA Transform templates are equal
+// TODO:
+//  This method should be included within TSecurityAssocSpec class.
+//
+//
+#ifdef SYMBIAN_IPSEC_VOIP_SUPPORT
+TBool
+CIPSecPolicyManagerHandler::IsEqualSaSpec(CSecpolBundleItem* aS1, 
+                                          CSecpolBundleItem* aS2) const
+    {
+    if ((!aS1 && aS2) || (!aS2 && aS1))
+        return (EFalse);
+            
+    if (aS1 && aS2)
+        {
+        if((aS1->iSpec) && (aS1->iSpec->iPropList) && (aS2->iSpec) && (aS2->iSpec->iPropList))
+            {
+            if (aS1->iSpec->iPropList->At(0)->iType != aS2->iSpec->iPropList->At(0)->iType)
+                return (EFalse);
+            if (aS1->iSpec->iPropList->At(0)->iAalg != aS2->iSpec->iPropList->At(0)->iAalg)
+                return (EFalse);
+            if (aS1->iSpec->iPropList->At(0)->iAalgLen != aS2->iSpec->iPropList->At(0)->iAalgLen)
+                return (EFalse);
+            if (aS1->iSpec->iPropList->At(0)->iEalg != aS2->iSpec->iPropList->At(0)->iEalg)
+                return (EFalse);
+            if (aS1->iSpec->iPropList->At(0)->iEalgLen != aS2->iSpec->iPropList->At(0)->iEalgLen)
+                return (EFalse);
+            if (aS1->iSpec->iSpec.iPfs != aS2->iSpec->iSpec.iPfs)
+                return (EFalse);
+            if (aS1->iSpec->iSpec.iReplayWindowLength != aS2->iSpec->iSpec.iReplayWindowLength)
+                return (EFalse);
+            
+            if (aS1->iSpec->iPropList->At(0)->iHard.sadb_lifetime_allocations != aS2->iSpec->iPropList->At(0)->iHard.sadb_lifetime_allocations)
+                return (EFalse);
+            if (aS1->iSpec->iPropList->At(0)->iHard.sadb_lifetime_bytes != aS2->iSpec->iPropList->At(0)->iHard.sadb_lifetime_bytes)
+                return (EFalse);
+            if (aS1->iSpec->iPropList->At(0)->iHard.sadb_lifetime_addtime != aS2->iSpec->iPropList->At(0)->iHard.sadb_lifetime_addtime)
+                return (EFalse);
+            if (aS1->iSpec->iPropList->At(0)->iHard.sadb_lifetime_usetime != aS2->iSpec->iPropList->At(0)->iHard.sadb_lifetime_usetime)
+                return (EFalse);
+            
+            if (aS1->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_allocations != aS2->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_allocations)
+                return (EFalse);
+            if (aS1->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_bytes != aS2->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_bytes)
+                return (EFalse);
+            if (aS1->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_addtime != aS2->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_addtime)
+                return (EFalse);
+            if (aS1->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_usetime != aS2->iSpec->iPropList->At(0)->iSoft.sadb_lifetime_usetime)
+                return (EFalse);
+            }
+        }
+        
+    return (ETrue);
+    }
+#else
+TBool
+CIPSecPolicyManagerHandler::IsEqualSaSpec(TSecurityAssocSpec* aS1, 
+                                          TSecurityAssocSpec* aS2) const
+    {
+    if ((!aS1 && aS2) || (!aS2 && aS1))
+        return (EFalse);
+            
+    if (aS1 && aS2)
+        {
+        if (aS1->iType != aS2->iType)
+            return (EFalse);
+        if (aS1->iAalg != aS2->iAalg)
+            return (EFalse);
+        if (aS1->iAalgLen != aS2->iAalgLen)
+            return (EFalse);
+        if (aS1->iEalg != aS2->iEalg)
+            return (EFalse);
+        if (aS1->iEalgLen != aS2->iEalgLen)
+            return (EFalse);
+        if (aS1->iPfs != aS2->iPfs)
+            return (EFalse);
+        if (aS1->iReplayWindowLength != aS2->iReplayWindowLength)
+            return (EFalse);
+        
+        if (aS1->iHard.sadb_lifetime_allocations != aS2->iHard.sadb_lifetime_allocations)
+            return (EFalse);
+        if (aS1->iHard.sadb_lifetime_bytes != aS2->iHard.sadb_lifetime_bytes)
+            return (EFalse);
+        if (aS1->iHard.sadb_lifetime_addtime != aS2->iHard.sadb_lifetime_addtime)
+            return (EFalse);
+        if (aS1->iHard.sadb_lifetime_usetime != aS2->iHard.sadb_lifetime_usetime)
+            return (EFalse);
+        
+        if (aS1->iSoft.sadb_lifetime_allocations != aS2->iSoft.sadb_lifetime_allocations)
+            return (EFalse);
+        if (aS1->iSoft.sadb_lifetime_bytes != aS2->iSoft.sadb_lifetime_bytes)
+            return (EFalse);
+        if (aS1->iSoft.sadb_lifetime_addtime != aS2->iSoft.sadb_lifetime_addtime)
+            return (EFalse);
+        if (aS1->iSoft.sadb_lifetime_usetime != aS2->iSoft.sadb_lifetime_usetime)
+            return (EFalse);
+        }
+        
+    return (ETrue);
+    }
+#endif // SYMBIAN_IPSEC_VOIP_SUPPORT
+//
+//  Find gateway that matches with gateway parameter given by the client. 
+//  This function is a part of GetAvailableSelectors function.
+//
+//
+void CIPSecPolicyManagerHandler::FillSelectorInfoObject()
+	{
+	// Set the base for the selector list
+    CSecurityPolicy* sp = iPieceData->Policies();
+    CSelectorList* selectorList = sp->SelectorList();
+    TInt selectorCount = selectorList->Count();
+    TIpsecSelectorInfo selectorInfo;
+    
+    TInt count = 0;
+    
+    if(iTunnel.IsUnspecified())
+    	{
+    	return;
+    	}
+    
+    for (TInt i = 0; i < selectorCount; i++)
+        {
+        CPolicySelector* policySelector = selectorList->At(i);
+        
+        TSecpolBundleIter iter(policySelector->iBundle);
+        CSecpolBundleItem* item = NULL;
+        
+        while (iter)
+        	{
+        	item = (CSecpolBundleItem *)iter++;
+        	count++;
+        	if(item)
+        		{
+        		if(item->iTunnel.Family() == iTunnel.Family())
+        			{
+        			if(item->iTunnel.Address() == iTunnel.Address())
+        				{
+      					// set the gateway address, sa index,remote address, remote port, remote mask, 
+      					// direction, local address, local port, local mask and protocol to the 
+      					//client's address space in selectorinfo object
+      					selectorInfo.iTunnel.SetAddress(item->iTunnel.Address());
+        				selectorInfo.iSaIndex = count;
+        				selectorInfo.iDirection = policySelector->iDirection;
+						
+						selectorInfo.iRemote.SetAddress(policySelector->iRemote.Address());
+						selectorInfo.iRemote.SetPort(policySelector->iRemote.Port());
+						selectorInfo.iRemoteMask.SetAddress(policySelector->iRemoteMask.Address());
+						
+						selectorInfo.iLocal.SetAddress(policySelector->iLocal.Address());
+						selectorInfo.iLocal.SetPort(policySelector->iLocal.Port());
+						selectorInfo.iLocalMask.SetAddress(policySelector->iLocalMask.Address());
+						
+						selectorInfo.iProtocol = policySelector->iProtocol;
+						iSelectorInfoArray->AppendL(selectorInfo);
+						
+					   }
+        			}
+        		}
+        	}
+        }
+
+	}
+
+
+
+