--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcpiputils/dnd/src/servers.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,683 @@
+// Copyright (c) 2004-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:
+// servers.cpp - server manager module
+//
+
+#include "servers.h"
+#include "engine.h"
+#include "inet6log.h"
+#include "dns_hdr.h" // only for KDnsPort!
+#include "dnd.hrh"
+
+// Item of the server list, hold DNS server information
+class TDnsServerData
+ {
+public:
+ TInetAddr iAddr; //< DNS Server Address
+ TDnsServerScope iScope; //< The Sever Scope and type (MC/UC)
+ TInt iServerId; //< Id of the server
+ TInt iInterface; //< Index to Interface Array
+ };
+
+// Item of the interface list, hold interface information for DNS
+class TDnsInterfaceData
+ {
+public:
+ TName iName; //< Name of the interface
+ TUint32 iScope[16]; //< The scope vector
+ };
+
+// Item of the configured servers list
+class TDnsConfiguredServer
+ {
+public:
+ TName iName;
+ TInetAddr iAddr;
+ };
+
+class CDnsServerManager : public CBase, public MDnsServerManager
+ {
+ ~CDnsServerManager();
+public:
+ CDnsServerManager(CDndEngine &aControl);
+ void ConstructL();
+ void ConfigurationChanged();
+
+ //
+ // MDnsServerManager API
+ // (for docs, see the MDnsServerManger definitions)
+ //
+ TInt OpenList(const TDnsServerFilter &aFilter, MDnsServerListNotify *aNotify);
+ TInt Count(const TDnsServerFilter &aFilter) const;
+ TInt Next(const TDnsServerFilter &aFilter, TInt aServerId) const;
+ void CloseList(const TDnsServerFilter &aFilter);
+
+ TInt Address(TInt aServerId, TInetAddr &aAddr) const;
+ TUint32 Scope(TInt aServerId, const TInetAddr &aAddr);
+ TInt ServerId(const TInetAddr &aAddr) const;
+ TUint32 NameSpace(const TDnsServerFilter &aFilter, TInt aServerId) const;
+ TInt BuildServerList();
+ void AddServerAddress(const TName &aInterface, const TInetAddr &aAddr);
+ void LockByAddress(const TInetAddr &aAddr, TUint32 aNid, TDnsServerFilter &aFilter);
+
+private:
+ // Build and add interface entry to the list (basic operation)
+ TInt AddInterfaceEntry(const TSoInetIfQuery &aInfo);
+ // Find interface matching the destination address
+ TInt FindInterface(const TInetAddr &aAddr);
+ // Add new server address to the server list
+ void AddToServerList(const TInetAddr &aAddr, TInt aIf, RSocket &aSocket);
+ // Add new interface to the interface list
+ TInt AddToInterfaceList(const TSoInetInterfaceInfo &aInfo, RSocket &aSocket);
+ // Compare the filter with a DNS server
+ TBool Match(const TDnsServerFilter &aFilter, const TDnsServerData &aServer) const;
+
+ CDndEngine &iControl;
+ TUint32 iServerId; //< The last used server id.
+ TTime iMark; //< The time of the last configuration change.
+ TUint iConfigure:1; //< Reconfigure needed, if set.
+ TUint iStable:1; //< = 1, when scanned list is supposed to be stable
+ TUint iCacheFlushed:1; //< = 1, when cache has been flushed (only used with "FlushOnConfig" ini-option)
+
+ CArrayFixFlat<TDnsServerData> *iServerList; //< Current list of servers
+ CArrayFixFlat<TDnsInterfaceData> *iInterfaceList; //< Current list of interfaces
+ CArrayFixFlat<TDnsConfiguredServer> *iConfiguredList; //< Current list of configured servers
+ };
+
+
+MDnsServerManager *DnsServerManager::NewL(CDndEngine &aControl)
+ {
+ CDnsServerManager *mgr = new (ELeave) CDnsServerManager(aControl);
+
+ CleanupStack::PushL(mgr);
+ mgr->ConstructL();
+ CleanupStack::Pop();
+ return mgr;
+ }
+
+//
+// CDnsServerManager
+//
+
+CDnsServerManager::CDnsServerManager(CDndEngine &aControl) : iControl(aControl)
+ {
+ }
+
+void CDnsServerManager::ConstructL()
+ {
+ iServerList = new (ELeave) CArrayFixFlat<TDnsServerData>(2);
+ iInterfaceList = new (ELeave) CArrayFixFlat<TDnsInterfaceData>(5);
+ // iConfiguredList is allocated only if required.
+ }
+
+void CDnsServerManager::ConfigurationChanged()
+ {
+ LOG(Log::Printf(_L("CDnsServerManager -- Configuration changed")));
+ // Just flag that building a new server list is needed. Try
+ // to delay heavy interface scanning operation until really
+ // needed (because configuration changes may come in burts).
+ iConfigure = 1;
+ iStable = 0;
+ iCacheFlushed = 0;
+ iMark.UniversalTime();
+ }
+
+CDnsServerManager::~CDnsServerManager()
+ {
+ delete iServerList;
+ delete iInterfaceList;
+ delete iConfiguredList;
+ }
+
+// CDnsServerManager::AddInterfaceData
+TInt CDnsServerManager::AddInterfaceEntry(const TSoInetIfQuery &aInfo)
+ {
+ TRAPD(err,
+ TDnsInterfaceData &ifd = iInterfaceList->ExtendL();
+ ifd.iName = aInfo.iName;
+ for (TInt i = sizeof(ifd.iScope) / sizeof(ifd.iScope[0]); --i >= 0; )
+ ifd.iScope[i] = aInfo.iZone[i];
+ );
+ return err < 0 ? err : iInterfaceList->Count() - 1;
+ }
+
+// CDnsServerManager::AddToInterfaceList
+// *************************************
+/**
+// Add the interface to the interface list, if it does not already exist.
+// The existence is based on comparing the interface names.
+//
+// @param aInfo the information that identifies the interface
+// @param aSocket (must be open) to be used for GetOpt, if needed
+// @returns
+// @li < 0, if there are some errors (interface was not added)
+// @li index to the interface (>= 0) in the interface list.
+*/
+TInt CDnsServerManager::AddToInterfaceList(const TSoInetInterfaceInfo &aInfo, RSocket &aSocket)
+ {
+ if (aInfo.iName.Length() == 0)
+ return -1; // Interface must have a name.
+ //
+ // Check if interface already exists and don't insert duplicates
+ //
+ TInt i;
+ for (i = iInterfaceList->Count(); --i >= 0; )
+ {
+ const TDnsInterfaceData &data = iInterfaceList->At(i);
+ if (data.iName.Compare(aInfo.iName) == 0)
+ return i; // Interface already present in the list
+ }
+ //
+ // A new interface, get the scope vector
+ //
+ TPckgBuf<TSoInetIfQuery> opt;
+ opt().iName = aInfo.iName;
+ const TInt err = aSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, opt);
+ return err < 0 ? err : AddInterfaceEntry(opt());
+ }
+
+// CDnsServerManager::FindInterface
+// ********************************
+//
+TInt CDnsServerManager::FindInterface(const TInetAddr &aAddr)
+ {
+ TPckgBuf<TSoInetIfQuery> opt;
+ opt().iDstAddr = aAddr;
+ const TInt err = iControl.iSocket.GetOpt(KSoInetIfQueryByDstAddr, KSolInetIfQuery, opt);
+ if (err < 0)
+ return err;
+
+ // Check if interface is already known
+
+ for (TInt i = iInterfaceList->Count(); --i >= 0; )
+ {
+ const TDnsInterfaceData &data = iInterfaceList->At(i);
+ if (data.iName.Compare(opt().iName) == 0)
+ return i;
+ }
+ // Not present yet, just add it
+ return AddInterfaceEntry(opt());
+ }
+
+// CDnsServerManager::AddToServerList
+// **********************************
+/**
+// Add new address to the server list. A new entry is only
+// added if the address does not already exist.
+//
+// @param aAddr address of the DNS server
+// @param aIf the interface (index to the interface list)
+*/
+void CDnsServerManager::AddToServerList(const TInetAddr &aAddr, TInt aIf, RSocket &aSocket)
+ {
+ if (aAddr.IsUnspecified())
+ return; // No address, nothing to add
+ //
+ // Normalize all addresses into IPv6 format
+ //
+ TDnsServerData sd;
+ sd.iAddr = aAddr;
+ sd.iInterface = aIf;
+ if (sd.iAddr.Family() == KAfInet)
+ sd.iAddr.ConvertToV4Mapped();
+ else if (sd.iAddr.Family() != KAfInet6)
+ return; // Only IPv4 or IPv6 addresses are valid
+ if (sd.iAddr.IsMulticast())
+ // sd.iScope = (TDnsServerScope)(sd.iAddr.Ip6Address().Scope());
+ sd.iScope = EDnsServerScope_MC_LOCAL;
+ else
+ sd.iScope = EDnsServerScope_UC_GLOBAL;
+
+ if (!sd.iAddr.Port())
+ sd.iAddr.SetPort(KDnsPort);
+
+ LOG(TBuf<80> dst);
+ LOG(sd.iAddr.OutputWithScope(dst));
+ LOG(TBuf<80> src);
+ // In typhoon and later, DND never activates interfaces. All
+ // usable server addresses must have a valid route, before
+ // they can be used. Thus, check it...
+ //
+ TPckgBuf<TSoInetIfQuery> opt;
+ opt().iDstAddr = aAddr;
+ const TBool has_route =
+ (aSocket.GetOpt(KSoInetIfQueryByDstAddr, KSolInetIfQuery, opt) == KErrNone) && !opt().iSrcAddr.IsUnspecified();
+ LOG(opt().iSrcAddr.OutputWithScope(src));
+ if (!has_route)
+ {
+ LOG(Log::Printf(_L("\t\tnameserver [%S] (src=%S) has no route or no source address, skipped"), &dst, &src));
+ return; // No route, unusable for now -- ignore
+ }
+ //
+ // Check if address already exists and don't insert duplicates
+ //
+ for (TInt i = iServerList->Count(); --i >= 0; )
+ {
+ TDnsServerData &a = iServerList->At(i);
+ if (a.iAddr.Match(sd.iAddr) && a.iAddr.Scope() == sd.iAddr.Scope())
+ {
+ // However, if server didn't have assigned
+ // interface yet, assign it from this call.
+ //
+ if (a.iInterface < 0)
+ a.iInterface = aIf;
+ LOG(Log::Printf(_L("\t\tnameserver (id=%d) [%S] (src=%S)"), a.iServerId, &dst, &src));
+ return; // Duplicate address, do not add again.
+ }
+ }
+
+ sd.iServerId = ++iServerId; // Assign a "server id"
+ LOG(Log::Printf(_L("\t\tnameserver (id=%d) [%S] (src=%S) (new)"), sd.iServerId, &dst, &src));
+ TRAP_IGNORE(iServerList->AppendL(sd));
+ }
+
+// CDnsServerManager::BuildServerList
+// **********************************
+TInt CDnsServerManager::BuildServerList()
+ {
+ LOG(Log::Printf(_L("CDnsServerManager -- Scanning interfaces and building the server list")));
+ TInt err = KErrNone;
+
+ // Refresh the current list of DNS server addresses
+ // (this could be skipped if there was some definite way of knowing
+ // that nothing has changed since the last collect...)
+
+ // Use Delete instead of Reset, so that space is reused? (not freed and reallocated)
+ iInterfaceList->Delete(0, iInterfaceList->Count());
+
+ // Trying to keep "server id" stable, thus do not clear existing
+ // server list, but just mark entries, so that unused ones can be
+ // reclaimed after build is complete.
+ for (TInt i = iServerList->Count(); --i >= 0; )
+ iServerList->At(i).iInterface = -2;
+
+ LOG(Log::Printf(_L("\t* Scanning interfaces")));
+ // Read the DNS address from the interface
+ TSoInetInterfaceInfo *info = new TSoInetInterfaceInfo; // allocate large struct from heap!
+ if (info && (err = iControl.iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl)) == KErrNone)
+ {
+ TPckg<TSoInetInterfaceInfo> opt(*info);
+ while (iControl.iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone)
+ {
+ if (opt().iName.Length() == 0)
+ continue; // "null" interface, ignore
+ if (!opt().iAddress.IsUnspecified())
+ {
+#ifdef _LOG
+ TBuf<60> tmp;
+ opt().iAddress.OutputWithScope(tmp);
+ Log::Printf(_L("\t%S [%S]"), &opt().iName, &tmp);
+#endif
+ TInt i = AddToInterfaceList(opt(), iControl.iSocket);
+ AddToServerList((TInetAddr &)(opt().iNameSer1), i, iControl.iSocket);
+ AddToServerList((TInetAddr &)(opt().iNameSer2), i, iControl.iSocket);
+ }
+ else
+ {
+ LOG(Log::Printf(_L("\tInterface: %S [no address, skipping]"), &opt().iName));
+ }
+ }
+ }
+ delete info;
+ LOG(Log::Printf(_L("\t* Configured interface specific addresses")));
+
+ //
+ // Add configured servers, if a matching interface has become available
+ // (assumes that configured list and interface list are always short, so
+ // the loop over all lists is not too bad...)
+ if (iConfiguredList)
+ {
+ for (TInt i = iConfiguredList->Count(); --i >= 0; )
+ {
+ const TDnsConfiguredServer &cs = iConfiguredList->At(i);
+ for (TInt j = iInterfaceList->Count(); --j >= 0; )
+ {
+ const TDnsInterfaceData &data = iInterfaceList->At(j);
+ if (data.iName.Compare(cs.iName) == 0)
+ {
+ // Complete the address with the scope id
+ // from the interface!
+ TInetAddr addr(cs.iAddr);
+ if (addr.Family() == KAfInet)
+ addr.ConvertToV4Mapped();
+ const TUint s = addr.Ip6Address().Scope() - 1;
+ if (s < 16)
+ {
+ addr.SetScope(data.iScope[s]);
+ AddToServerList(addr, j, iControl.iSocket);
+ }
+ break;
+ }
+ }
+ }
+ }
+ //
+ // Remove unused servers from the list
+ //
+ LOG(Log::Printf(_L("\t* Remove stale addresses")));
+ const TInt N = iServerList->Count();
+ TInt k = 0;
+ for (TInt j = 0; j < N; ++j)
+ {
+ const TDnsServerData &a = iServerList->At(j);
+ if (a.iInterface != -2)
+ {
+ // This server entry is still used
+ if (k != j)
+ iServerList->At(k) = a;
+ k++;
+ }
+#ifdef _LOG
+ else
+ {
+ TBuf<80> tmp;
+ a.iAddr.OutputWithScope(tmp);
+ Log::Printf(_L("\t\tnameserver (id=%d) [%S] deleted"), a.iServerId, &tmp);
+ }
+#endif
+ }
+ if (k < N)
+ {
+ iServerList->Delete(k, N - k);
+ }
+
+ LOG(Log::Printf(_L("CDnsServerManager -- Done, current server count=%d"), iServerList->Count()));
+ return err;
+ }
+
+// CDnsServerManager::AddServerAddress
+// ***********************************
+void CDnsServerManager::AddServerAddress(const TName &aInterface, const TInetAddr &aAddr)
+ {
+ if (iConfiguredList == NULL &&
+ (iConfiguredList = new CArrayFixFlat<TDnsConfiguredServer>(5)) == NULL)
+ return; // No memory for the allocation, ignore..
+
+ // Do not add duplicates, check existing entries
+ for (TInt i = iConfiguredList->Count(); --i >= 0; )
+ {
+ const TDnsConfiguredServer &cs = iConfiguredList->At(i);
+ if (cs.iName.Compare(aInterface) == 0 && cs.iAddr.Match(aAddr))
+ return; // Duplicate!
+ }
+
+ iConfigure = 1; // Request rebuild of server list.
+
+ TRAP_IGNORE(TDnsConfiguredServer &cf = iConfiguredList->ExtendL();
+ cf.iAddr = aAddr;
+ cf.iName = aInterface;
+ );
+ }
+
+/**
+// @param aFilter the server filter
+// @parma aServer to be tested against the filter
+// @returns
+// @li TRUE, if the server matches the filter
+// @li FALSE, if the server does not match the filter
+*/
+TBool CDnsServerManager::Match(const TDnsServerFilter &aFilter, const TDnsServerData &aServer) const
+ {
+ if (aFilter.iServerScope != aServer.iScope)
+ return FALSE;
+ if (aFilter.iLockType < KIp6AddrScopeNodeLocal || aFilter.iLockType > KIp6AddrScopeNetwork)
+ return FALSE; // actually invalid locking scope level
+
+ // If a server address is specified without interface (-1), then this
+ // server will match any filter (if server scopes are same).
+ if (aServer.iInterface >= 0)
+ {
+ const TDnsInterfaceData &id = iInterfaceList->At(aServer.iInterface);
+ if (aFilter.iLockId != id.iScope[aFilter.iLockType-1])
+ return FALSE; // Not in locked scope
+ }
+ return TRUE;
+ }
+
+
+//
+// MDnsServerManager API
+//
+TInt CDnsServerManager::OpenList(const TDnsServerFilter &aFilter, MDnsServerListNotify * /*aNotify*/)
+ {
+ if (iConfigure)
+ {
+ const TInt err = BuildServerList();
+ if (err != KErrNone)
+ return err;
+ iConfigure = 0;
+ }
+ if (iStable)
+ return KErrNone;
+
+ if (iControl.GetConfig().iFlushOnConfig && iCacheFlushed == 0)
+ {
+ iCacheFlushed = 1;
+ TRAP_IGNORE(iControl.HandleCommandL(EDndFlush));
+ }
+
+ TTime stamp;
+ stamp.UniversalTime();
+ TTimeIntervalSeconds elapsed;
+ stamp.SecondsFrom(iMark, elapsed);
+ if (elapsed.Int() > (TInt)iControl.GetConfig().iSetupTime)
+ {
+ iStable = 1;
+ return KErrNone;
+ }
+ if (aFilter.iServerScope == EDnsServerScope_MC_LOCAL)
+ return KErrNone;
+ // We are still within setup time, return "pending" if no servers available
+ return (Count(aFilter) == 0) ? 1 : KErrNone;
+ }
+
+TInt CDnsServerManager::Count(const TDnsServerFilter &aFilter) const
+ {
+ TInt count = 0;
+ for (TInt i = iServerList->Count(); --i >= 0; )
+ if (Match(aFilter, iServerList->At(i)))
+ ++count;
+ return count;
+ }
+
+TInt CDnsServerManager::Next(const TDnsServerFilter &aFilter, TInt aServerId) const
+ {
+ const TInt N = iServerList->Count();
+
+ TInt wrap = 0;
+ TInt first_found = 0;
+ TInt current_found = 0;
+
+ if (aServerId == 0)
+ {
+ //
+ // When "current" server is not specified, Next will
+ // return the first server (specified by iServerId)
+ //
+ for (TInt i = 0; i < N; ++i)
+ {
+ const TDnsServerData &server = iServerList->At(i);
+ if (server.iServerId == aFilter.iServerId)
+ first_found = 1;
+ if (first_found)
+ {
+ if (Match(aFilter, server))
+ return server.iServerId;
+ }
+ else if (wrap == 0 && Match(aFilter, server))
+ wrap = server.iServerId;
+ }
+ //
+ // iServerId server is not present (or it and none
+ // of the servers after it do not match). Return
+ // the first matching server.
+ return wrap;
+ }
+ else
+ {
+ //
+ // When aServerId is given, the Next will return
+ // the next matching server between (current, first)
+ // (or fail, if none exists)
+ for (TInt i = 0; i < N; ++i)
+ {
+ const TDnsServerData &server = iServerList->At(i);
+ if (current_found)
+ {
+ if (server.iServerId == aFilter.iServerId)
+ return 0; // Back to first, no Matching server
+ if (Match(aFilter, server))
+ return server.iServerId;
+ }
+ else
+ {
+ if (server.iServerId == aServerId)
+ // Start looking for the next match
+ current_found = 1;
+ if (server.iServerId == aFilter.iServerId)
+ first_found = 1;
+ if (first_found == 0 && wrap == 0 && Match(aFilter, server))
+ wrap = server.iServerId;
+ }
+ }
+ //
+ // Wrap around wrapping
+ //
+ if (current_found && first_found)
+ return wrap;
+ }
+ return 0; // No matching next server!
+ }
+
+void CDnsServerManager::CloseList(const TDnsServerFilter &/*aFilter*/)
+ {
+ }
+
+
+TInt CDnsServerManager::Address(TInt aServerId, TInetAddr &aAddr) const
+ {
+ const TInt N = iServerList->Count();
+ for (TInt i = 0; i < N; ++i)
+ {
+ const TDnsServerData &server = iServerList->At(i);
+ if (server.iServerId == aServerId)
+ {
+ aAddr = server.iAddr;
+ return KErrNone;
+ }
+ }
+ return KErrNotFound;
+ }
+
+TInt CDnsServerManager::ServerId(const TInetAddr &aAddr) const
+ {
+ for (TInt i = iServerList->Count(); --i >= 0; )
+ {
+ const TDnsServerData &server = iServerList->At(i);
+ if (server.iAddr.CmpAddr(aAddr) && server.iAddr.Scope() == aAddr.Scope())
+ return server.iServerId;
+ }
+ return 0;
+ }
+
+TUint32 CDnsServerManager::Scope(TInt aServerId, const TInetAddr &aAddr)
+ {
+ const TInt N = iServerList->Count();
+ for (TInt i = 0; i < N; ++i)
+ {
+ const TDnsServerData &server = iServerList->At(i);
+ if (server.iServerId == aServerId)
+ {
+ const TUint i = aAddr.Ip6Address().Scope() - 1;
+ if (i > 15)
+ return 0; // Bad scope level.
+ const TInt j = server.iInterface < 0 ? FindInterface(server.iAddr) : server.iInterface;
+ if (j >= 0)
+ return (iInterfaceList->At(j)).iScope[i];
+ }
+ }
+ return 0;
+ }
+
+
+static TUint32 MakeNameSpaceId(TInt aServerScope, const TDnsInterfaceData &aIf)
+ {
+ //
+ // Construct the name space id from the server scope and
+ // matching scope id.
+ //
+ if (aServerScope < 0)
+ aServerScope = -aServerScope;
+ aServerScope -= 1;
+ if (aServerScope >= 0 && aServerScope < 16)
+ return (aIf.iScope[aServerScope] & ~(0xFu << 28)) | ((aServerScope & 0xFu) << 28);
+ return 0;
+ }
+
+TUint32 CDnsServerManager::NameSpace(const TDnsServerFilter &aFilter, TInt aServerId) const
+ {
+ if (aFilter.iLockType < KIp6AddrScopeNodeLocal || aFilter.iLockType > KIp6AddrScopeNetwork)
+ return 0; // actually invalid locking type
+
+ if (aServerId)
+ {
+ const TInt N = iServerList->Count();
+ for (TInt i = 0; i < N; ++i)
+ {
+ const TDnsServerData &server = iServerList->At(i);
+ if (server.iServerId == aServerId)
+ {
+ if (server.iInterface < 0)
+ break;
+ return MakeNameSpaceId(aFilter.iServerScope, iInterfaceList->At(server.iInterface));
+ }
+ }
+ // Should this fall to generic search if server is not
+ // found? Or, just return 0?
+ }
+
+ for (TInt i = iInterfaceList->Count(); --i >= 0; )
+ {
+ TDnsInterfaceData &id = iInterfaceList->At(i);
+ if (aFilter.iLockId == id.iScope[aFilter.iLockType-1])
+ return MakeNameSpaceId(aFilter.iServerScope, id);
+ }
+ // Cannot find name space id
+ return 0;
+ }
+
+void CDnsServerManager::LockByAddress(const TInetAddr &aAddr, TUint32 aNid, TDnsServerFilter &aFilter)
+ {
+ aFilter.iLockType = aAddr.Ip6Address().Scope();
+ aFilter.iLockId = aAddr.Scope();
+ if (aFilter.iLockId)
+ return; // Address specified the scope id, all done.
+ if (aFilter.iLockType == KIp6AddrScopeNetwork)
+ {
+ aFilter.iLockId = aNid;
+ return; // If lock scope level is network, we can use aNid as is.
+ }
+
+ // Address does not specify the scope id. Try to pick one
+ // from known interfaces based on the network id.
+ for (TInt i = iInterfaceList->Count(); --i >= 0; )
+ {
+ TDnsInterfaceData &id = iInterfaceList->At(i);
+ if (aNid == id.iScope[KIp6AddrScopeNetwork-1])
+ {
+ aFilter.iLockId = id.iScope[aFilter.iLockType-1];
+ break;
+ }
+ }
+ }