tcpiputils/dnd/src/llmnrnotifyhandler.cpp
changeset 0 af10295192d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcpiputils/dnd/src/llmnrnotifyhandler.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,234 @@
+// 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:
+// llmnrnotifyhandler.cpp - Link-local multicast name resolution 
+// notify handler
+// CDndLlmnrNotifyHandler
+//
+
+#ifdef LLMNR_ENABLED
+
+#if defined(TCPIP6_USE_COMMDB)
+#	include <commdb.h>
+#else
+#	include <commsdattypesv1_1.h>
+#       include <commsdattypesv1_1_partner.h>
+	using namespace CommsDat;
+#endif
+
+#include "engine.h"
+#include "llmnrresponder.h"
+#include "inet6log.h"
+
+CDndLlmnrNotifyHandler::CDndLlmnrNotifyHandler(CDndLlmnrResponder &aMaster)
+ : iTimeout(CLlmnrNotifyHandlerTimeoutLinkage::Timeout), iMaster(aMaster)
+ 	{
+ 	}
+
+CDndLlmnrNotifyHandler::~CDndLlmnrNotifyHandler()
+	{
+	iTimeout.Cancel();
+	}
+
+void CDndLlmnrNotifyHandler::ConstructL()
+	{
+	LOG(Log::Printf(_L("CDndLlmnrNotifyHandler::ConstructL() size=%d\r\n"), (TInt)sizeof(*this)));
+	}
+
+void CDndLlmnrNotifyHandler::ConfigurationChanged()
+	{
+	iMaster.iControl.Timer().Set(iTimeout, iMaster.iLlmnrConf->iNotifyTime);
+	}
+
+void CDndLlmnrNotifyHandler::ScanInterfaces()
+	{
+	(void)iMaster.iControl.CheckResult
+		(_L("Setting Socket options"),
+		 iMaster.iControl.iSocket.SetOpt(KSoInetEnumInterfaces,
+		 KSolInetIfCtrl));
+
+	TSoInetInterfaceInfo *info = new TSoInetInterfaceInfo; // allocate large struct from heap!
+	if (info == NULL)
+		return; // No memory!
+	TPckg<TSoInetInterfaceInfo> opt(*info);
+
+	TPckgBuf<TSoInetIfQuery> opt2;
+	opt2().iName.SetLength(0);
+
+	TUint32 iap_id = 0;			// Current IAP ID (== iZone[1])
+	TInt llmnr_disabled = 0;	// (init just to silence warning! this value is never used).
+
+	iMaster.UpdateStart();
+	while(iMaster.iControl.iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone)
+		{
+		// Check address configured
+		if(opt().iAddress.IsUnspecified())
+			continue; // No address, ignore
+		// KSoInetNextInterface returns an entry for each configured
+		// address. Skip entry, if previous entry was the same real
+		// interface. [This is only optimization that lessens the
+		// generated log messages--not for speed].
+		if (opt().iName.Compare(opt2().iName) == 0)
+			continue;
+		opt2().iName = opt().iName;
+		TInt err = iMaster.iControl.iSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, opt2);
+		if(err != KErrNone)
+			{
+			LOG(Log::Printf(_L("CDndLlmnrNotifyHandler::ScanInterfaces GetOpt KSoInetIfQueryByName error: %d"),err));
+			}
+		else
+			{
+			LOG(Log::Printf(_L("CDndLlmnrNotifyHandler::ScanInterfaces - Interface up, name: %S\r\n"), &opt().iName));
+
+			if (iap_id != opt2().iZone[1])
+				{
+				// Different IAP, need to find whether LLMNR is to be enabled or disabled
+				iap_id = opt2().iZone[1];
+				TRAPD(err, llmnr_disabled = IsLlmnrDisabledL(iap_id));
+				if (err != KErrNone)
+					llmnr_disabled = 1;	// By default (if no configuration present), disable it.
+				}
+			TIpVer ipver;
+			if(opt().iAddress.Family() == KAfInet || opt().iAddress.IsV4Mapped())
+				ipver = EIPv4;
+			else
+				ipver = EIPv6;
+			iMaster.UpdateInterface(opt2().iName, ipver, opt2().iZone, opt().iHwAddr, llmnr_disabled);
+			}
+		}
+	delete info;
+	iMaster.UpdateFinish();
+	}
+
+void CDndLlmnrNotifyHandler::Timeout(const TTime &)
+	{
+	LOG(Log::Printf(_L("--> CDndLlmnrNotifyHandler::Timeout() -start-")));
+	ScanInterfaces();
+	LOG(Log::Printf(_L("<-- CDndLlmnrNotifyHandler::Timeout() -exit-")));
+	}
+
+
+
+/**
+* Acquire LLMNR configuration flag for the IAP from the CommDB.
+*
+* @return
+*	@li 0, if configuration not found or LLMNR is enabled by the configuration
+*	@li 1, if LLMNR is disabled by the configuration.
+*
+* Leave is implicit disable.
+*/
+TInt CDndLlmnrNotifyHandler::IsLlmnrDisabledL(TUint32 aIap)
+	{
+	TBool enable = 1;	// If CommsDB does not have SERVICE_ENABLE_LLMNR, the default is enabled!
+#if defined(TCPIP6_USE_COMMDB)
+#	ifdef SERVICE_ENABLE_LLMNR
+	CCommsDatabase* db = CCommsDatabase::NewL();
+	CleanupStack::PushL(db);	// cleanup 1
+
+	CCommsDbTableView* iap = db->OpenViewMatchingUintLC(TPtrC(IAP), TPtrC(COMMDB_ID), aIap);	// cleanup 2
+	User::LeaveIfError(iap->GotoFirstRecord());
+	TBuf<KCommsDbSvrMaxFieldLength> service_type;
+	TUint32 service;
+	iap->ReadTextL(TPtrC(IAP_SERVICE_TYPE), service_type);
+	iap->ReadUintL(TPtrC(IAP_SERVICE), service);
+	CCommsDbTableView *srv = db->OpenViewMatchingUintLC(service_type, TPtrC(COMMDB_ID), service);	// cleanup 3
+	User::LeaveIfError(srv->GotoFirstRecord());
+	srv->ReadBoolL(TPtrC(SERVICE_ENABLE_LLMNR), enable);
+	CleanupStack::PopAndDestroy(3);
+#	else
+	(void)aIap;
+#	endif
+#else
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+	CMDBSession *dB = CMDBSession::NewLC(KCDVersion1_2);
+#else
+	CMDBSession *dB = CMDBSession::NewLC(KCDVersion1_1);
+#endif
+
+	
+	// Reveal hidden or private IAP records if a licensee has chosen to protect a record
+	// using one of these flags - the API to do this is public so internal components
+	// have to support the use of such records.
+	dB->SetAttributeMask( ECDHidden | ECDPrivate );
+
+	CCDIAPRecord* iap = static_cast<CCDIAPRecord *>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
+	CleanupStack::PushL(iap);
+	iap->SetRecordId(aIap);
+	LOG(Log::Printf(_L("IsLlmnrDisabledL: LoadL for IAP=%d"), aIap));
+	iap->LoadL(*dB);
+	LOG(Log::Printf(_L("IsLlmnrDisabledL: LoadL OK, doing LoadL for service")));
+#if 0
+	iap->iService.LoadL(*dB);
+#else
+	const TDesC& servType = iap->iServiceType;
+
+	if (servType.CompareF(TPtrC(KCDTypeNameDialOutISP))==0)
+		{
+		iap->iService.iLinkedRecord = static_cast<CCDDialOutISPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDialOutISPRecord));
+		}
+	else if (servType.CompareF(TPtrC(KCDTypeNameDialInISP))==0)
+		{
+		iap->iService.iLinkedRecord = static_cast<CCDDialInISPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDialInISPRecord));
+		}
+	else if (servType.CompareF(TPtrC(KCDTypeNameLANService))==0)
+		{
+		iap->iService.iLinkedRecord = static_cast<CCDLANServiceRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdLANServiceRecord));
+		}
+	else if (servType.CompareF(TPtrC(KCDTypeNameWLANServiceExt))==0)
+		{
+		iap->iService.iLinkedRecord = static_cast<CCDWLANServiceExtRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdWLANServiceExtRecord));
+		}
+	else if (servType.CompareF(TPtrC(KCDTypeNameVPNService))==0)
+		{
+		iap->iService.iLinkedRecord = static_cast<CCDVPNServiceRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdVPNServiceRecord));
+		}
+	else if (servType.CompareF(TPtrC(KCDTypeNameVPNService))==0)
+		{
+		iap->iService.iLinkedRecord = static_cast<CCDVPNServiceRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdVPNServiceRecord));
+		}
+	else if (servType.CompareF(TPtrC(KCDTypeNameOutgoingWCDMA))==0)
+		{
+		iap->iService.iLinkedRecord = static_cast<CCDOutgoingGprsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdOutgoingGprsRecord));
+		}
+	else if (servType.CompareF(TPtrC(KCDTypeNameIncomingWCDMA))==0)
+		{
+		iap->iService.iLinkedRecord = static_cast<CCDIncomingGprsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIncomingGprsRecord));
+		}
+	else if (servType.CompareF(TPtrC(KCDTypeNameDefaultWCDMA))==0)
+		{
+		iap->iService.iLinkedRecord = static_cast<CCDDefaultWCDMARecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDefaultWCDMARecord));
+		}
+	else
+		{
+		LOG(Log::Printf(_L("CDndLlmnrNotifyHandler::IsLlmnrDisabledL() service type not supported (%S)\r\n"), &servType));
+		goto fail;
+		}
+	iap->iService.iLinkedRecord->SetRecordId(iap->iService);
+	iap->iService.iLinkedRecord->LoadL(*dB);
+#endif
+fail:
+	CCDServiceRecordBase *const ptrService = static_cast<CCDServiceRecordBase *>(iap->iService.iLinkedRecord);
+	LOG(Log::Printf(_L("IsLlmnrDisabledL: LoadL for service returns=[%u]"), (TInt)ptrService));
+	if (ptrService)
+		enable = ptrService->iServiceEnableLlmnr;
+	else
+		enable = 0;
+	CleanupStack::PopAndDestroy(2);		
+#endif
+	LOG(Log::Printf(_L("IsLlmnrDisabledL: enable=%d"), enable));
+	return enable == 0;
+	}
+
+
+#endif