tcpiputils/dhcp/te_dhcp/src/te_dhcpTestServer.cpp
changeset 0 af10295192d8
child 21 abbed5a4b42a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcpiputils/dhcp/te_dhcp/src/te_dhcpTestServer.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,899 @@
+// Copyright (c) 2003-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:
+// for (WINS && EKA1) versions will be xxxServer.Dll and require a thread to be started
+// in the process of the client. The client initialises the server by calling the
+// one and only ordinal.
+// On EKA2 this is an exe.
+// 
+//
+
+/**
+ @file te_dhcpTestServer.cpp
+*/
+
+#include <in_sock.h>
+
+#include "te_dhcpTestServer.h"
+#include "te_dhcpTestStep1.h"
+#include "te_dhcpTestStep2.h"
+#include "te_dhcpTestStep3.h"
+#include "te_dhcpTestStep4.h"
+#include "te_dhcpTestStep5.h"
+#include "te_dhcpTestStep6.h"
+#include "te_dhcpTestCommandSteps.h"
+#include "te_dhcpTestStepOOM.h"
+#include "te_dhcpserverteststep.h"
+
+#include <in6_opt.h>
+#include <commdbconnpref.h>
+#include <commsdattypesv1_1.h>
+
+#define _DEBUG_DHCP_STATE_NAMES
+#include "../../include/DHCPStatesDebug.h"
+
+CDhcpTestServer* CDhcpTestServer::NewL()
+/**
+* @return - Instance of the test server
+* Called inside the MainL() function to create and start the
+* CTestServer derived server.
+*/
+	{
+	CDhcpTestServer * server = new (ELeave) CDhcpTestServer();
+	CleanupStack::PushL(server);
+	// CServer base class call
+	server->StartL(server->ServerName());
+
+	CleanupStack::Pop(server);
+	return server;
+	}
+
+
+#if (!defined EKA2)
+LOCAL_C void MainL()
+/**
+* REQUIRES semaphore to sync with client as the Rendezvous()
+* calls are not available
+*/
+	{
+	CActiveScheduler* sched=NULL;
+	sched = new(ELeave) CActiveScheduler;
+	CleanupStack::PushL(sched);
+	CActiveScheduler::Install(sched);
+
+	CDhcpTestServer* server = NULL;
+
+	TRAPD(err,server = CDhcpTestServer::NewL());
+	// if there is an error, then we don't want to be doing all the
+	// fancy stuff, just cleanup, adnd the rest is taken care of
+	// for us...
+	if(!err)
+		{
+		CleanupStack::PushL(server);
+		RSemaphore sem;
+		// The client API will already have created the semaphore
+		User::LeaveIfError(sem.OpenGlobal(KServerName));
+		CleanupStack::Pop(server);
+		// Sync with the client then enter the active scheduler
+		sem.Signal();
+		sem.Close();
+		sched->Start();
+		}
+	delete server;
+	CleanupStack::PopAndDestroy(sched);
+	}
+#else
+// EKA2 much simpler
+// Just an E32Main and a MainL()
+LOCAL_C void MainL()
+/**
+* Much simpler, uses the new Rendezvous() call to sync with the client
+*/
+	{
+	// Leave the hooks in for platform security
+#if (defined __DATA_CAGING__)
+	RProcess().DataCaging(RProcess::EDataCagingOn);
+	RProcess().SecureApi(RProcess::ESecureApiOn);
+#endif
+	CActiveScheduler* sched=NULL;
+	sched = new(ELeave) CActiveScheduler;
+	CleanupStack::PushL(sched);
+	CActiveScheduler::Install(sched);
+
+	CDhcpTestServer* server = NULL;
+	// Create the CTestServer derived server
+	TRAPD(err,server = CDhcpTestServer::NewL());
+	// if there is an error, then we don't want to be doing all the
+	// fancy stuff, just cleanup, adnd the rest is taken care of
+	// for us...
+	if(!err)
+		{
+		// Sync with the client and enter the active scheduler
+		RProcess::Rendezvous(KErrNone);
+#ifdef _DEBUG
+		RProperty::Define(KMyPropertyCat, KMyPropertyDestPortv4, RProperty::EInt, TSecurityPolicy(TSecurityPolicy::EAlwaysPass),
+					TSecurityPolicy(ECapabilityWriteDeviceData));
+		RProperty::Define(KMyPropertyCat, KMyPropertyDestPortv6, RProperty::EInt, TSecurityPolicy(TSecurityPolicy::EAlwaysPass),
+					TSecurityPolicy(ECapabilityWriteDeviceData));
+		RProperty::Set(KMyPropertyCat, KMyPropertyDestPortv4, 67);	// set to default values
+		RProperty::Set(KMyPropertyCat, KMyPropertyDestPortv6, 547);	// set to default values
+        RProperty::Define(KMyPropertyCat, KMyDefaultLeaseTime, RProperty::EInt, TSecurityPolicy(TSecurityPolicy::EAlwaysPass),
+                    TSecurityPolicy(ECapabilityWriteDeviceData));
+        RProperty::Set(KMyPropertyCat, KMyDefaultLeaseTime, 21600);	// Define and set default values for server lease time
+#endif
+		sched->Start();
+		}
+	delete server;
+	CleanupStack::PopAndDestroy(sched);
+	}
+#endif
+
+// Only a DLL on emulator for typhoon and earlier
+#if (defined __WINS__ && !defined EKA2)
+TInt ThreadFunc (TAny* /*aParam*/)	// define the ordinal 1 on eka1
+#else			
+GLDEF_C TInt E32Main()	// define 32main if eka2...
+#endif
+/**
+* @return - Standard Epoc error code on exit
+*/
+	{
+	CTrapCleanup* cleanup = CTrapCleanup::New();
+	if(cleanup == NULL)
+		{
+		return KErrNoMemory;
+		}
+	TInt err = KErrNone;
+	TRAP(err,MainL());
+	delete cleanup;
+	return err;
+    }
+
+#if (defined __WINS__ && !defined EKA2)
+/**
+  * Define this helper function to start a new thread in the client
+  * process for WINS and EKA1...
+  */
+EXPORT_C TInt NewServer() 
+/**
+* @return - Standard Epoc error codes
+* 1st and only ordinal, called by the client API to initialise the server
+*/
+	{
+	RThread thread;
+	
+	TBuf<KMaxTestExecuteNameLength> threadName(KServerName);
+	// Create a hopefully unique thread name and use the ThreadFunc
+	const TInt KMaxHeapSize = 0x1000000;			//< Allow a 1Mb max heap
+	TInt err = thread.Create(threadName, ThreadFunc, KDefaultStackSize,
+								KMinHeapSize, KMaxHeapSize, NULL, EOwnerProcess);
+	if (err)
+		{
+		return err;
+		}
+	thread.Resume();
+	thread.Close();
+	return KErrNone;
+	}
+
+
+GLDEF_C TInt E32Dll(enum TDllReason)
+	{
+	return 0;
+	}
+#endif
+
+
+
+CTestStep* CDhcpTestServer::CreateTestStep(const TDesC& aStepName)
+/**
+* @return - A CTestStep derived instance
+* Implementation of CTestServer pure virtual
+*/
+	{
+	CDhcpTestStepBase* testStep = NULL;
+	// This server creates just one step but create as many as you want
+	// They are created "just in time" when the worker thread is created
+	if(aStepName == KDhcpTestStep1_1)
+		testStep = new CDhcpTestStep1_1();
+	else if(aStepName == KDhcpTestStep1_2)
+		testStep = new CDhcpTestStep1_2();
+	else if(aStepName == KDhcpTestStep1_3)
+		testStep = new CDhcpTestStep1_3();
+	else if(aStepName == KDhcpTestStep1_4)
+		testStep = new CDhcpTestStep1_4();
+	else if(aStepName == KDhcpTestStep1_5)
+		testStep = new CDhcpTestStep1_5();
+	else if(aStepName == KDhcpTestStep1_6)
+		testStep = new CDhcpTestStep1_6();
+	else if(aStepName == KDhcpTestStep1_7)
+		testStep = new CDhcpTestStep1_7();
+	else if(aStepName == KDhcpTestStep1_8)
+		testStep = new CDhcpTestStep1_8();
+	
+	else if(aStepName == KDhcpTestStep2_1)
+		testStep = new CDhcpTestStep2_1();
+	else if(aStepName == KDhcpTestStep2_2)
+		testStep = new CDhcpTestStep2_2();
+	else if(aStepName == KDhcpTestStep2_3)
+		testStep = new CDhcpTestStep2_3();
+	else if(aStepName == KDhcpTestStep2_4)
+		testStep = new CDhcpTestStep2_4();
+	else if(aStepName == KDhcpTestStep2_5)
+		testStep = new CDhcpTestStep2_5();
+	else if(aStepName == KDhcpTestStep2_6)
+		testStep = new CDhcpTestStep2_6();
+	else if(aStepName == KDhcpTestStep2_7)
+		testStep = new CDhcpTestStep2_7();
+	else if(aStepName == KDhcpTestStep2_8)
+		testStep = new CDhcpTestStep2_8();
+	else if(aStepName == KDhcpTestStep2_9)
+		testStep = new CDhcpTestStep2_9();
+    else if(aStepName == KDhcpTestStep2_GetRaw)
+		testStep = new CDhcpTestStep2_GetRaw();
+	else if(aStepName == KDhcpTestStep2_11)
+		testStep = new CDhcpTestStep2_11();
+    else if(aStepName == KDhcpTestStep2_12)
+		testStep = new CDhcpTestStep2_12();		
+    else if(aStepName == KDhcpTestStep2_ClearMOFlag)
+        testStep = new CDhcpTestStep2_ClearMOFlag();
+    else if(aStepName == KDhcpTestStep2_NoRAandDHCPServ)
+        testStep = new CDhcpTestStep2_NoRAandDHCPServ(); 
+	else if(aStepName == KDhcpTestStep2_GetSIPAddrViaDHCP)
+		testStep = new CDhcpTestStep2_GetSIPAddrViaDHCP();
+	else if(aStepName == KDhcpTestStep2_GetSIPAddrViaPCOBuffer)
+		testStep = new CDhcpTestStep2_GetSIPAddrViaPCOBuffer();
+    else if(aStepName == KDhcpTestStep2_GetSIPDomain)
+		testStep = new CDhcpTestStep2_GetSIPDomain();	
+	else if(aStepName == KDhcpTestStep2_GetSIPAddrFailure)
+		testStep = new CDhcpTestStep2_GetSIPAddrFailure();
+	else if(aStepName == KDhcpTestStep2_GetSIPAddrBufferOverrun)
+		testStep = new CDhcpTestStep2_GetSIPAddrBufferOverrun();
+	else if(aStepName == KDhcpTestStep2_GetSIPServerAddrIndexChecker)
+		testStep = new CDhcpTestStep2_GetSIPServerAddrIndexChecker();
+	else if(aStepName == KDhcpTestStep2_GetSIPServerAddrNegativeIndexChecker)
+		testStep = new CDhcpTestStep2_GetSIPServerAddrNegativeIndexChecker();
+    #ifdef SYMBIAN_TCPIPDHCP_UPDATE
+	/* PREQ1898 DHCPv6 test cases */
+	else if(aStepName == KDhcpTestStep2_DomainSearchList_Test1)
+		testStep = new CDhcpTestStep2_DomainSearchList_Test1();	
+	else if(aStepName == KDhcpTestStep2_DomainSearchList_Test2)
+		testStep = new CDhcpTestStep2_DomainSearchList_Test2();	
+	else if(aStepName == KDhcpTestStep2_DomainSearchList_Test3)
+		testStep = new CDhcpTestStep2_DomainSearchList_Test3();	
+	else if(aStepName == KDhcpTestStep2_DomainSearchList_Test4)
+		testStep = new CDhcpTestStep2_DomainSearchList_Test4();	
+	else if(aStepName == KDhcpTestStep2_DomainSearchList_Test5)
+		testStep = new CDhcpTestStep2_DomainSearchList_Test5();	
+	
+	else if(aStepName == KDhcpTestStep2_DNSServerList_Test1)
+		testStep = new CDhcpTestStep2_DNSServerList_Test1();	
+	else if(aStepName == KDhcpTestStep2_DNSServerList_Test2)
+		testStep = new CDhcpTestStep2_DNSServerList_Test2();	
+	else if(aStepName == KDhcpTestStep2_DNSServerList_Test3)
+		testStep = new CDhcpTestStep2_DNSServerList_Test3();	
+	else if(aStepName == KDhcpTestStep2_DNSServerList_Test4)
+		testStep = new CDhcpTestStep2_DNSServerList_Test4();	
+	else if(aStepName == KDhcpTestStep2_DNSServerList_Test5)
+		testStep = new CDhcpTestStep2_DNSServerList_Test5();		
+
+	else if(aStepName == KDhcpTestStep2_MultipleParams_Test1)
+		testStep = new CDhcpTestStep2_MultipleParams_Test1();
+	else if(aStepName == KDhcpTestStep2_MultipleParams_Test2)
+		testStep = new CDhcpTestStep2_MultipleParams_Test2();	
+	else if(aStepName == KDhcpTestStep2_MultipleParams_Test3)
+		testStep = new CDhcpTestStep2_MultipleParams_Test3();	
+	else if(aStepName == KDhcpTestStep2_MultipleParams_Test4)
+		testStep = new CDhcpTestStep2_MultipleParams_Test4();		
+	else if(aStepName == KDhcpTestStep2_MultipleParams_Test5)
+		testStep = new CDhcpTestStep2_MultipleParams_Test5();	
+	
+	else if(aStepName == KDhcpTestStep2_GetRaw_Test1)
+		testStep = new CDhcpTestStep2_GetRaw_Test1();
+	else if(aStepName == KDhcpTestStep2_GetRaw_Test2)
+		testStep = new CDhcpTestStep2_GetRaw_Test2();	
+	/* End of PREQ 1898 test case */
+    #endif //SYMBIAN_TCPIPDHCP_UPDATE 
+	
+	else if(aStepName == KDhcpTestStep3_1)
+		testStep = new CDhcpTestStep3_1();
+	else if(aStepName == KDhcpTestStep3_2)
+		testStep = new CDhcpTestStep3_2();
+	else if(aStepName == KDhcpTestStep3_3)
+		testStep = new CDhcpTestStep3_3();		
+	else if(aStepName == KDhcpTestStep3_4)
+		testStep = new CDhcpTestStep3_4();
+	
+	else if(aStepName == KDhcpTestStep4_1)
+		testStep = new CDhcpTestStep4_1();
+	else if(aStepName == KDhcpTestStep4_2)
+		testStep = new CDhcpTestStep4_2();
+	else if(aStepName == KDhcpTestStep4_3)
+		testStep = new CDhcpTestStep4_3();
+
+	// tests in section 5 cannot be run automatically
+	// overnight, but may be able to run on hardware
+	else if(aStepName == KDhcpTestStep5_1)
+		testStep = new CDhcpTestStep5_1();
+	else if(aStepName == KDhcpTestStep5_2)
+		testStep = new CDhcpTestStep5_2();
+	else if(aStepName == KDhcpTestStep5_3)
+		testStep = new CDhcpTestStep5_3();
+	else if(aStepName == KDhcpTestStep5_4)
+		testStep = new CDhcpTestStep5_4();
+	else if(aStepName == KDhcpTestStep5_5)
+		testStep = new CDhcpTestStep5_5();
+	else if(aStepName == KDhcpTestStep5_6)
+		testStep = new CDhcpTestStep5_6();
+	else if(aStepName == KDhcpTestStep5_7)
+		testStep = new CDhcpTestStep5_7();
+	else if(aStepName == KDhcpTestStep5_8)
+		testStep = new CDhcpTestStep5_8();
+
+	if(aStepName == KDhcpTestStep12_1)
+		testStep = new CDhcpTestStep12_1();
+
+	else if(aStepName == KDhcpTestStepOOM_1)
+		testStep = new CDhcpTestStepOOM_1();
+	
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER
+//tests added for the DHCP server implementation and run manually
+
+	else if(aStepName == KDhcpTestStep2_23)
+		testStep = new CDhcpTestStep2_23();
+	else if(aStepName == KDhcpTestStep2_24)
+		testStep = new CDhcpTestStep2_24();
+	else if(aStepName == KDhcpTestStep2_25)
+		testStep = new CDhcpTestStep2_25();
+	else if(aStepName == KDhcpTestStepOOM_2)
+		testStep = new CDhcpTestStepOOM_2();
+		
+#endif // SYMBIAN_NETWORKING_DHCPSERVER		
+		
+	// commands
+	else if(aStepName == KDhcpTestCommandSetAddressMode)
+		testStep = new CDhcpTestCommandSetAddressMode();
+	else if(aStepName == KDhcpTestCommandSetIAPToUse)
+		testStep = new CDhcpTestCommandSetIAPToUse();
+	else if(aStepName == KDhcpTestCommandSetDebugFlags)
+		testStep = new CDhcpTestCommandSetDebugFlags();
+	else if(aStepName == KDhcpTestCommandSetIPv4LinkLocal)
+		testStep = new CDhcpTestCommandSetIPv4LinkLocal();
+	
+#ifdef  SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+
+	else if(aStepName == KDhcpTestStep2_26)
+		testStep = new CDhcpTestStep2_26();
+	else if(aStepName == KDhcpTestStep2_27)
+		testStep = new CDhcpTestStep2_27();
+	else if(aStepName == KDhcpTestStep2_28)
+		testStep = new CDhcpTestStep2_28();
+	else if(aStepName == KDhcpTestStep2_29)
+		testStep = new CDhcpTestStep2_29();
+	else if(aStepName == KDhcpTestStep2_30)
+		testStep = new CDhcpTestStep2_30();
+	else if(aStepName == KDhcpTestStep2_31)
+		testStep = new CDhcpTestStep2_31();
+	else if(aStepName == KDhcpTestStep2_32)
+		testStep = new CDhcpTestStep2_32();
+	else if(aStepName == KDhcpTestStep2_33)
+		testStep = new CDhcpTestStep2_33();
+	else if(aStepName == KDhcpTestStep2_34)
+		testStep = new CDhcpTestStep2_34();
+	else if(aStepName == KDhcpTestStep2_35)
+		testStep = new CDhcpTestStep2_35();
+	else if(aStepName == KDhcpTestStep2_36)
+		testStep = new CDhcpTestStep2_36();
+	else if(aStepName == KDhcpTestStep2_37)
+		testStep = new CDhcpTestStep2_37();
+	else if(aStepName == KDhcpTestStep2_38)
+		testStep = new CDhcpTestStep2_38();
+	else if(aStepName == KDhcpTestStep2_39)
+		testStep = new CDhcpTestStep2_39();
+	else if(aStepName == KDhcpTestStep2_40)
+		testStep = new CDhcpTestStep2_40();	
+	else if(aStepName == KDhcpTestStep2_41)
+		testStep = new CDhcpTestStep2_41();	
+	else if(aStepName == KDhcpTestStepOOM_3)
+		testStep = new CDhcpTestStepOOM_3();
+		
+#endif //SYMBIAN_NETWORKING_DHCP_MSG_HEADERS  			
+	
+  /* Added for DHCP testing with Codenomicon tool*/			
+	else if(aStepName == KDhcpTestStepCodenomicon1)
+		testStep = new CDhcpTestStepCodenomicon1();	
+	else if(aStepName == KDhcpTestStepCodenomicon2)
+		testStep = new CDhcpTestStepCodenomicon2();	
+	else if(aStepName == KDhcpTestStepServ_1)
+	    testStep = new CDhcpTestStepServ_1(); 
+	else if(aStepName == KDhcpTestStepServ_2)
+	    testStep = new CDhcpTestStepServ_2(); 
+	else if(aStepName == KDhcpTestStepServ_3)
+	    testStep = new CDhcpTestStepServ_3(); 
+	else if(aStepName == KDhcpTestStepServ_4)
+			testStep = new CDhcpTestStepServ_4(); 
+	else if(aStepName == KDhcpTestStepServ_5)
+			testStep = new CDhcpTestStepServ_5(); 
+	else if(aStepName == KDhcpTestStepServ_6)
+			testStep = new CDhcpTestStepServ_6(); 
+	
+	if(testStep)
+		{
+		testStep->SetTestServer(this);
+		}
+			
+	return testStep;
+	}
+
+
+//----------------------------------------------------------------------------------
+
+/**
+ * sets the test server to be used by the test step for storing / accessing
+ *  data which persists across test steps (e.g. IAP to use, IPv6 mode)
+ */   
+void CDhcpTestStepBase::SetTestServer(CDhcpTestServer* aServ)
+	{
+	iTestServer = aServ;
+	}
+
+/**
+ * sets whether we're in IPv6 mode
+@leave   if the test server is not available.
+ */   
+void CDhcpTestStepBase::Set_UsingIPv6L(TBool aIP6)
+	{
+	User::LeaveIfNull(iTestServer);
+	iTestServer->iUsingIPv6 = aIP6;
+
+	}
+
+/**
+ * sets which IAP subsequent test cases should use
+@leave   if the test server is not available.
+ */   
+void CDhcpTestStepBase::SetIAPToUseL(TInt aIAP)
+	{
+	User::LeaveIfNull(iTestServer);
+	iTestServer->iIAPToUse = aIAP;
+	}
+
+
+/**
+* adds the ECDPrivate attribute to the IAP record - any component trying to access this record will require the ReadDeviceData capability
+@leave   if the test server is not available or the IAP record with the specified ID cannot be retrieved and modified by commsdat
+*/
+void CDhcpTestStepBase::MakeIAPPrivateL( TInt id )
+	{
+	// Create a session which can view hidden records if necessary.
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+	CMDBSession* session = CMDBSession::NewLC(KCDVersion1_2);
+#else
+	CMDBSession* session = CMDBSession::NewLC(KCDVersion1_1);
+#endif
+	session->SetAttributeMask( ECDHidden | ECDPrivate );
+	
+	// Load the IAP record.
+	CCDIAPRecord* iapRecord = static_cast<CCDIAPRecord*>( CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
+	CleanupStack::PushL( iapRecord );
+    iapRecord->SetRecordId( id );
+	iapRecord->LoadL( *session );
+
+	// Make it private.
+	iapRecord->SetAttributes( iapRecord->Attributes() | ECDPrivate );
+	iapRecord->ModifyL( *session );
+
+	// Cleanup.
+	CleanupStack::Pop();
+	CleanupStack::Pop();
+	}
+
+
+/**
+@return  ETrue if we are using ipv6, and EFalse otherwise.
+@leave   if the value from test server can't be obtained.
+*/   
+TBool CDhcpTestStepBase::UsingIPv6L(void) const
+{
+	User::LeaveIfNull(iTestServer);
+	return iTestServer->iUsingIPv6;
+}
+
+/**
+@return  the IAP we're currently set to use
+@leave   if the value from test server can't be obtained.
+*/   
+TInt CDhcpTestStepBase::IAPToUseL(void)
+	{
+	User::LeaveIfNull(iTestServer);
+	TInt iap = iTestServer->iIAPToUse;
+	if(iap == 0)
+		{
+		INFO_PRINTF1(_L("You must use the SetIAPToUse test step before running this test"));
+		User::Leave(KErrArgument); 
+		}
+	return iap;
+	}
+
+/**
+@leave   if the value from commsdat can't be obtained.
+*/   
+void CDhcpTestStepBase::InitialServiceLinkL( CMDBSession* aDbSession, CCDIAPRecord* aIapRecord )
+	{
+	// This will be made more simple quite soon when commsdat supports linked records
+	//
+	if (aIapRecord->iService.iLinkedRecord == 0)
+		{
+		const TDesC& servType = aIapRecord->iServiceType;
+		__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CCDHCPDb::InitialServiceLinkL() service type = \"%S\""), &servType));
+		if (servType.CompareF(TPtrC(KCDTypeNameDialOutISP))==0)
+			{
+			aIapRecord->iService.iLinkedRecord = static_cast<CCDDialOutISPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDialOutISPRecord));
+			}
+		else if (servType.CompareF(TPtrC(KCDTypeNameDialInISP))==0)
+			{
+			aIapRecord->iService.iLinkedRecord = static_cast<CCDDialInISPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDialInISPRecord));
+			}
+		else if (servType.CompareF(TPtrC(KCDTypeNameLANService))==0)
+			{
+			aIapRecord->iService.iLinkedRecord = static_cast<CCDLANServiceRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdLANServiceRecord));
+			}
+		else if (servType.CompareF(TPtrC(KCDTypeNameVPNService))==0)
+			{
+			aIapRecord->iService.iLinkedRecord = static_cast<CCDVPNServiceRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdVPNServiceRecord));
+			}
+		else
+			{
+			__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CCDHCPDb::InitialServiceLinkL() Invalid Service Type!!!")));
+			User::Leave(KErrBadName);	
+			}
+		
+		aIapRecord->iService.iLinkedRecord->SetRecordId(aIapRecord->iService);
+		}
+
+	aIapRecord->iService.iLinkedRecord->LoadL(*aDbSession);
+	}
+
+/**
+@return  ETrue if the IAP we are using or EFalse otherwise
+@leave   if the value from commsdat can't be obtained.
+*/   
+TBool CDhcpTestStepBase::IsIAPAddrStaticL()
+	{
+	// Create a session which can view hidden records if necessary.
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+	CMDBSession* session = CMDBSession::NewLC(KCDVersion1_2);
+#else
+	CMDBSession* session = CMDBSession::NewLC(KCDVersion1_1);
+#endif
+	
+	session->SetAttributeMask( ECDHidden | ECDPrivate );
+	
+	// Load the IAP record.
+	CCDIAPRecord* iapRecord = static_cast<CCDIAPRecord*>( CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
+	CleanupStack::PushL( iapRecord );
+    iapRecord->SetRecordId( IAPToUseL() );
+	iapRecord->LoadL( *session );
+
+	// Get the service record.
+	CCDServiceRecordBase* service;
+	InitialServiceLinkL( session, iapRecord );
+	service = static_cast<CCDServiceRecordBase*>(iapRecord->iService.iLinkedRecord);
+
+	// Read any statically assigned IP address.
+	TInetAddr addr;
+	TInt ignoreThis;
+	CMDBField<TBool>* addrFromServer = static_cast<CMDBField<TBool>*>( service->GetFieldByNameL( KCDTypeNameIpAddrFromServer, ignoreThis ) );
+	if( !*addrFromServer )
+		{
+		CMDBField<TDesC>* cdbAddr = static_cast<CMDBField<TDesC>*>( service->GetFieldByNameL( KCDTypeNameIpAddr, ignoreThis ) );
+		addr.Input( *cdbAddr );
+		}
+
+	// Cleanup.
+	CleanupStack::PopAndDestroy();
+	CleanupStack::PopAndDestroy();
+	
+	return !addr.IsUnspecified();
+	}
+
+/**
+@return Flags listing the currently configured address types.
+@leave   if any system error occurs.
+*/
+TUint CDhcpTestStepBase::GetCurrentAddressTypesL( RSocket &socket )
+{
+	TUint flags = KCurAddrNone;
+	TPtr8 empty( NULL, 0 );
+
+	// Query the size of the buffer required.
+	TInt listLength = socket.GetOpt( KSoInetAddressInfo, KSolInetIfQuery, empty );
+	
+	if( listLength > 0 )
+		{
+		// Allocate the buffer and read the list of addresses.
+		TInetAddressInfo* addrInfoBuffer = new(ELeave) TInetAddressInfo[listLength];
+		TPtr8 opt( (TUint8* )addrInfoBuffer, listLength * sizeof( TInetAddressInfo ) );
+		if( socket.GetOpt( KSoInetAddressInfo, KSolInetIfQuery, opt ) == KErrNone )
+			{
+			listLength = opt.Length() / (TInt)sizeof( TInetAddressInfo );
+
+			for( TInt count = 0; count < listLength; count ++ )
+				{
+				// Check that the address has been assigned.
+				if( ( addrInfoBuffer[count].iState == TInetAddressInfo::EAssigned ) ||
+					( addrInfoBuffer[count].iState == TInetAddressInfo::ETentative ) )
+					{
+					TIp6Addr& addr( addrInfoBuffer[count].iAddress );
+					TInetAddr inetAddr = TInetAddr( addr, 0 );
+
+					if( !inetAddr.IsUnspecified() && !inetAddr.IsLoopback() )
+						{
+						TBuf<39> addrStr;
+						inetAddr.Output( addrStr );
+						
+						 // Some addresses seem to be set to the IPv6 family which causes
+						 // IsLinkLocal to match using the IPv6 link local mask but not the
+						 // IPv4 link local mask.  We test manually as well which should be
+						 // safe as ZEROCONF randomly generated link-locals can only be created
+						 // during IPv4 testing.
+						if( inetAddr.IsLinkLocal() ||
+							( ( INET_ADDR( inetAddr.Ptr()[10], inetAddr.Ptr()[11], inetAddr.Ptr()[12], inetAddr.Ptr()[13] ) & KInetAddrLinkLocalNetMask ) == KInetAddrLinkLocalNet ) )
+							{
+							flags |= KCurAddrIPv4LinkLocal;
+							
+							INFO_PRINTF2( _L( "Linklocal address %S found on interface"), &addrStr );
+							}
+						else
+							{
+							flags |= KCurAddrGlobal;
+
+							INFO_PRINTF2( _L( "Global address %S found on interface"), &addrStr );
+							}
+						}
+					}
+				}
+			}
+		}
+		
+	if( flags == KCurAddrNone )
+		{
+		INFO_PRINTF1( _L( "No addresses found on interface") );
+		}
+	
+	return flags;
+}
+
+
+
+/**
+@return KAfInet6 or KAfInet depending on the test configuration (see test .ini file)
+@leave   if the value from ini file can't be obtained.
+*/
+TUint   CDhcpTestStepBase::IpAddressFamilyL(void)
+{
+    return UsingIPv6L() ? KAfInet6 :  KAfInet;
+}
+
+/**
+    Test step preamble. Just prints out which type AddrFamily we use.
+*/
+TVerdict	CDhcpTestStepBase::doTestStepPreambleL()
+{
+    if(UsingIPv6L())
+    {
+        INFO_PRINTF1(_L("KAfInet6 Address Family selected"));    
+    }
+    else
+    {
+        INFO_PRINTF1(_L("KAfInet Address Family selected"));    
+    }
+    
+    INFO_PRINTF2(_L("This test step will use IAP %d"), IAPToUseL());
+    
+	iConnPrefs.SetIapId(IAPToUseL());
+	iConnPrefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
+
+    return EPass;
+}
+
+
+/**
+    Get raw option data either for ip4 of for ip6, depending on the test setting
+    @param  aConn    RConnection object, interface to the DHCP server
+    @param  aBufDes  buffer for option data
+    @param  aOptCode option code   
+    
+    @return IOCTL completion code
+*/
+TInt CDhcpTestStepBase::DhcpGetRawOptionDataL(RConnection &aConn, TDes8& aBufDes, TUint aOptCode)
+{
+	TUint dhcpOptName;
+    TRequestStatus stat;
+    
+	//-- DHCP option data structure is totally different for DHCPv4 and DHCPv6
+	//-- so, we need to handle getting raw option data separately for v4 and v6.
+	if(UsingIPv6L())
+	{//-- we are dealing with DHCPv6 
+        INFO_PRINTF1(_L("Getting DHCP6 raw option data")); 
+        TDhcp6RawOptionDataPckg pckg6(aBufDes);
+        pckg6.SetOpCode((TUint16)aOptCode);	// OPTION_CLIENTID
+
+        dhcpOptName = KConnGetDhcp6RawOptionData;
+	}
+	else
+	{//-- we are dealing with DHCPv4 
+    	INFO_PRINTF1(_L("Getting DHCP4 raw option data"));    
+    	TDhcp4RawOptionDataPckg pckg(aBufDes);
+    	pckg.SetOpCode((TUint8)aOptCode);	// the subnet mask
+    	
+    	dhcpOptName = KConnGetDhcp4RawOptionData; // the same as KConnGetDhcpRawOptionData
+	}
+	
+	// Get raw option data either for ip4 of ip6
+	aConn.Ioctl(KCOLConfiguration, dhcpOptName, stat, &aBufDes);
+    User::WaitForRequest(stat);
+    
+    return stat.Int();
+}
+
+void CDhcpTestStepBase::GetDebugHandleL(RConnection& aConn)
+	{
+    TRequestStatus stat;
+    TPckgBuf<TInt> pckg;
+	aConn.Ioctl(KCOLConfiguration, KDHCP_GetPubSubMonitorHandle, stat, &pckg);
+    User::WaitForRequest(stat);
+	if(stat.Int() != KErrNone)
+		{
+		INFO_PRINTF1(_L("Can't fetch debug handle from DHCP. Ensure it was built in debug mode"));
+		User::Leave(stat.Int());
+		}
+	iDebugHandle = pckg();
+	}
+
+void CDhcpTestStepBase::ImmediateCompletionTestL(RConnection& /*aConn*/)
+{
+	DHCPDebug::State state;
+
+	TBool bExpectImmediateCompletion;
+    if(GetBoolFromConfig(ConfigSection(),_L("ExpectImmediateCompletion"), bExpectImmediateCompletion) == EFalse)
+    	{
+		INFO_PRINTF1(_L("Couldn't read ExpectImmediateCompletion value from test ini file."));
+		SetTestStepResult(EFail);
+		User::Leave(KErrArgument);
+    	}
+
+    DHCPDebug::Readiness ready=DHCPDebug::EUnknown;
+    QUERY_READYL(ready);
+    
+    if( ready == DHCPDebug::EReady )
+    	{
+    	if( bExpectImmediateCompletion )
+    		{
+	    	INFO_PRINTF1(_L("DHCP shouldn't be ready so quickly after RConnection::Start completed"));
+			User::Leave(KErrUnknown);
+			}
+		else
+		    {
+		    INFO_PRINTF1(_L("As expected, DHCP is ready after RConnection::Start completed."));
+		    }
+		}
+	else if ( ready == DHCPDebug::ENotReady )
+		{
+		if( bExpectImmediateCompletion )
+			{
+			INFO_PRINTF1(_L("As expected, DHCP isn't yet ready though RConnection::Start completed."));
+			}
+		else
+		    {
+	    	INFO_PRINTF1(_L("DHCP should be ready after RConnection::Start completed"));
+			User::Leave(KErrUnknown);
+			}			
+		}
+	else
+    	{
+    	INFO_PRINTF1(_L("Couldn't read readiness state"));
+		User::Leave(KErrUnknown);
+    	}
+
+	LOG_STATEL;
+}
+
+const TPtrC CDhcpTestServer::ServerName() const
+	{
+
+	// On EKA2, test server runs in its own process.
+	// So we arrive at the server name using the exe from which it is loaded.
+	// This is useful when doing cap tests, as we create duplicate exe's using setcap then.
+	TParsePtrC serverName(RProcess().FileName());
+	return serverName.Name();
+	}
+
+TUint CDhcpTestStepBase::WAIT_FOR_STATE_CHANGE_WITH_TIMEOUTL( TUint aTimeout )
+/**
+* Waits for the DHCP state to change or for a timeout to occur.  Not implemented
+* as macro because it's too complicated.
+*
+* Returns aTimeout if the wait times-out or the remainder if the state changed
+* (guaranteed to be less than aTimeout and at least one microsecond).
+*/
+	{
+    TAutoClose<RTimer> timer;
+    User::LeaveIfError( timer.iObj.CreateLocal() );
+    timer.PushL();
+	
+	TRequestStatus propStatus;
+	TRequestStatus timerStatus;
+	
+	// Attach to the property.
+	TAutoClose<RProperty> a;
+	TUid u = TUid::Uid(0x101fd9c5);
+	User::LeaveIfError( a.iObj.Attach(u, (TUint)(DHCPDebug::EState + iDebugHandle)) );
+	a.PushL();
+	
+	// Subscribe to the property.
+	TRequestStatus pubStat;
+	a.iObj.Subscribe(pubStat);
+	
+	TTime startTime;
+	startTime.UniversalTime();
+	
+	// Start the timeout timer.
+	timer.iObj.After( timerStatus, aTimeout );
+	
+	// Wait for the property to change or the timer to timeout.
+	User::WaitForRequest( pubStat, timerStatus );
+	
+	a.iObj.Cancel();
+	timer.iObj.Cancel();
+
+	a.Pop();
+	timer.Pop();
+	
+	// Check to see if the property changed or the timer timed-out.
+	if( timerStatus.Int() == KErrNone )
+		{
+		return aTimeout;
+		}
+	else
+		{
+		User::LeaveIfError( pubStat.Int() );
+		}
+	
+	TTime endTime;
+	endTime.UniversalTime();
+		
+	return Min( Max( TInt( endTime.MicroSecondsFrom( startTime ).Int64() ), 1 ), aTimeout );
+	}
+
+void CDhcpTestStepBase::GetProvisioningMacL(TDesC16& aSectioName, const TDesC16& aKeyName, TDes8& aHwAddress) 
+    {
+    TPtrC macAddressString;
+    TInt macAddressLength = aHwAddress.Length();
+    if (!GetStringFromConfig(aSectioName, aKeyName, macAddressString))
+        {
+        User::Leave(KErrNotFound);
+        }
+    
+    aHwAddress.FillZ();
+    
+    TUint8 bitVal;
+    for (TInt index=0, offset=0; index < macAddressLength; index++)
+        {
+        TLex bitText(macAddressString.Mid(offset,2));
+        bitText.Val(bitVal, EHex);
+        aHwAddress.Append(bitVal);
+        offset+=2;
+        }
+    }
+