tcpiputils/dhcp/src/DHCPIP4StateMachine.cpp
changeset 0 af10295192d8
child 53 7e41d162e158
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcpiputils/dhcp/src/DHCPIP4StateMachine.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,1878 @@
+// 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:
+// Implements the DHCP IP4 statemachine helper functions
+// 
+//
+
+/**
+ @file DHCPIP4StateMachine.cpp
+ @internalTechnology
+*/
+#include <babitflags.h>
+#include <e32math.h>
+#include "DHCPIP4States.h"
+#include "DHCPServer.h"
+#ifndef SYMBIAN_COMMS_REPOSITORY
+#include <commdb.h>
+#else
+#include <metadatabase.h>
+#include <commsdattypesv1_1.h>
+#endif
+
+#ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION
+#include "dhcphwaddrmanager.h"
+#endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION
+using namespace DHCPv4;
+#ifdef SYMBIAN_COMMS_REPOSITORY
+using namespace CommsDat;
+#endif
+
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER
+const TUint16 KBroadCastFlagMask = 0x8000;
+#endif
+
+CDHCPIP4StateMachine::~CDHCPIP4StateMachine()
+/**
+  * Destructor of the If base class
+  *
+  * @internalTechnology
+  *
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::~CDHCPIP4StateMachine")));
+	}
+	
+#ifndef SYMBIAN_NETWORKING_DHCPSERVER
+CDHCPIP4StateMachine* CDHCPIP4StateMachine::NewL(RSocketServ& aEsock, RConnection& aConnection, const TName& aInterfaceName)
+/**
+  * Creates a new instance of this class
+  *
+  * @internalTechnology
+  *
+  */
+	{
+	CDHCPIP4StateMachine* stateMachine = new (ELeave) CDHCPIP4StateMachine(aEsock, aConnection, aInterfaceName);
+	CleanupStack::PushL(stateMachine);
+	stateMachine->ConstructL();
+	CleanupStack::Pop(stateMachine);
+	return stateMachine;
+	}
+#endif // SYMBIAN_NETWORKING_DHCPSERVER
+
+void CDHCPIP4StateMachine::ConstructL()
+/**
+  * Creates socket and connections for the object
+  *
+  *
+  *	@internalTechnology
+  *
+  */
+	{
+   CDHCPStateMachine::ConstructL();
+
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::ConstructL")));
+	
+  	ReAllocL(KDhcpMaxMsgSizeIP4);
+  	iDhcpMessage = new(ELeave)CDHCPMessageHeaderIP4(iFragment);
+	iMessageSender = new(ELeave)CMessageSender(this,iSocket,&iTaskStartedAt,KAfInet);
+
+	}
+
+void CDHCPIP4StateMachine::StartInitL(MStateMachineNotify* aStateMachineNotify, EInitialisationContext /*aInitialisationContext*/, TInt /*aUserTimeOut*/)
+/**
+  * StartInitL
+  *
+  * This function is called to start the init state machine
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::StartInitL")));
+	ASSERT(!iFirstState);
+	
+	iFirstState = new(ELeave) CDHCPIP4Init(*this);
+	CDHCPState* select = new(ELeave) CDHCPIP4Select(*this);
+	iFirstState->SetNext( select );
+	CDHCPState* request = new(ELeave) CDHCPIP4Request(*this);
+	select->SetNext( request );
+	request->SetNext( new(ELeave) CDHCPIP4WaitForDAD(*this) );
+
+	CDHCPStateMachine::Start(aStateMachineNotify);
+	}
+
+void CDHCPIP4StateMachine::StartInformL(MStateMachineNotify* aStateMachineNotify, TBool /*aStaticAddress*/)
+/**
+  * StartIniformL
+  *
+  * This function is called to start the inform static address state machine
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::StartInformL")));
+	ASSERT(!iFirstState);
+
+	iFirstState = new(ELeave) CDHCPIP4Inform(*this);
+	CDHCPState* request = new(ELeave) CDHCPIP4Request(*this);
+   iFirstState->SetNext( request );
+   request->SetNext( new(ELeave) CDHCPIP4WaitForDAD(*this) );
+	
+	CDHCPStateMachine::Start(aStateMachineNotify);
+	iCfgInfoOnly = ETrue;
+	}
+
+#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+void CDHCPIP4StateMachine::StartInformL(MStateMachineNotify* aStateMachineNotify)
+/**
+  * This function is called to send inform message if options are not 
+  * found in iValidMsg buffer
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::StartInformL Dynamic Inform Request")));
+	ASSERT(!iFirstState);
+
+	iFirstState = new(ELeave) CDHCPIP4Inform(*this);
+	CDHCPState* request = new(ELeave) CDHCPIP4Request(*this);
+	iFirstState->SetNext( request );
+	CDHCPStateMachine::Start(aStateMachineNotify);
+
+	}
+#endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+void CDHCPIP4StateMachine::StartRebootL(MStateMachineNotify* aStateMachineNotify)
+/**
+  * StartRebootL
+  *
+  * This function is called to start the reboot request state machine
+  * used when trying to start using a previously assigned address still
+  * with valid lease.
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::StartRebootL")));
+	ASSERT(!iFirstState);
+
+   iFirstState = new(ELeave) CDHCPIP4Reboot(*this);
+	CDHCPState* request = new(ELeave) CDHCPIP4Request(*this);
+   iFirstState->SetNext( request );
+   request->SetNext( new(ELeave) CDHCPIP4WaitForDAD(*this) );
+
+	CDHCPStateMachine::Start(aStateMachineNotify);
+	}
+
+void CDHCPIP4StateMachine::StartRenewL(MStateMachineNotify* aStateMachineNotify,TInt /*aUserTimeOut*/)
+/**
+  * StartRenewL
+  *
+  * This function is called to start the renew of lease state machine
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::StartRenew")));
+	ASSERT(!iFirstState);
+
+  	iFirstState = new(ELeave) CDHCPIP4Renew(*this);
+   iFirstState->SetNext( new(ELeave) CDHCPIP4WaitForDAD(*this) );
+
+   CDHCPStateMachine::Start(aStateMachineNotify);
+	}
+
+void CDHCPIP4StateMachine::StartRebindL(MStateMachineNotify* aStateMachineNotify)
+/**
+  * StartRebindL
+  *
+  * This function is called to start the rebind state machine
+  *
+  * @internalTechnology
+  */	
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::StartRebindL")));
+	ASSERT(!iFirstState);
+	
+	iFirstState = new(ELeave) CDHCPIP4Rebind(*this);
+   iFirstState->SetNext( new(ELeave) CDHCPIP4WaitForDAD(*this) );
+
+	CDHCPStateMachine::Start(aStateMachineNotify);
+	}
+
+void CDHCPIP4StateMachine::StartDeclineL(MStateMachineNotify* aStateMachineNotify)
+/**
+  * StartDeclineL
+  *
+  * This function is called to start the decline state machine
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::StartDeclineL")));
+	ASSERT(!iFirstState);
+	
+	iFirstState = new(ELeave) CDHCPIP4Decline(*this);
+	
+	CDHCPStateMachine::Start(aStateMachineNotify);
+	}
+
+void CDHCPIP4StateMachine::StartReleaseL(MStateMachineNotify* aStateMachineNotify)
+/**
+  * StartReleaseL
+  *
+  * This function is called to start the release state machine
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::StartReleaseL")));
+	ASSERT(!iFirstState);
+	
+	iFirstState = new(ELeave) CDHCPIP4Release(*this);
+	//iFirstState->SetNext( new(ELeave) CDHCPRemoveConfiguredAddress(*this));
+	
+	CDHCPStateMachine::Start(aStateMachineNotify);
+	}
+
+CDHCPState* CDHCPIP4StateMachine::ReceiveL(TRequestStatus* aStatus)
+/**
+  * Posts receive from on socket
+  *
+  * @note The iDHCPServerAddr in param 2 of the socket receivefrom
+  * is written into by the socket to say where the received message
+  * came from.
+  * @internalTechnology
+  *
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::Receive")));
+	
+	DhcpMessage()->InitialiseL();
+  	iIncomingMsgDataPtr.Set(iDhcpMessage->Message().Des());
+   ASSERT( iReceiving == EFalse );
+ 	iReceiving = ETrue;
+	iSocket.RecvFrom(iIncomingMsgDataPtr, iDHCPServerAddr, 0, *aStatus);
+   return static_cast<CDHCPState*>(iActiveEvent);
+	}
+
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER
+#ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION
+CDHCPIP4StateMachine* CDHCPIP4StateMachine::NewL(RSocketServ& aEsock, RConnection& aConnection, const TName& aInterfaceName,  CDhcpHwAddrManager* aDhcpHwAddrManager, TBool aDHCPServerImpl)
+#else
+CDHCPIP4StateMachine* CDHCPIP4StateMachine::NewL(RSocketServ& aEsock, RConnection& aConnection, const TName& aInterfaceName,TBool aDHCPServerImpl)
+#endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION
+/**
+  * Creates a new instance of this class
+  *
+  * @internalTechnology
+  *
+  */
+	{
+#ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION
+	CDHCPIP4StateMachine* stateMachine = new (ELeave) CDHCPIP4StateMachine(aEsock, aConnection, aInterfaceName, aDhcpHwAddrManager, aDHCPServerImpl);
+#else
+	CDHCPIP4StateMachine* stateMachine = new (ELeave) CDHCPIP4StateMachine(aEsock, aConnection, aInterfaceName,aDHCPServerImpl);
+#endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION	
+	CleanupStack::PushL(stateMachine);
+	stateMachine->ConstructL();
+	CleanupStack::Pop(stateMachine);
+	return stateMachine;
+	}
+
+TUint8 CDHCPIP4StateMachine::GetClientMessageTypeL() const
+/**
+  * Returns the message type from the DHCP message
+  * i.e. whether the message is an offer, ack, nak...
+  *
+  * @internalTechnology 
+  */
+	{
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	v4Msg->ParseClientMsgL();
+	v4Msg->Dump();	
+
+	return v4Msg->iOptions.GetMessageType();
+	}
+
+	
+CDHCPState* CDHCPIP4StateMachine::ReceiveOnPort67L(TRequestStatus* aStatus)
+/**
+  * Posts receive from on socket
+  *
+  * @note The iDHCPClientAddr in param 2 of the socket receivefrom
+  * is written into by the socket to say where the received message
+  * came from.
+  * @internalTechnology
+  *
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::ReceiveOnPort67L")));
+	
+	DhcpMessage()->InitialiseL();
+  	iIncomingMsgDataPtr.Set(iDhcpMessage->Message().Des());
+	ASSERT( iReceiving == EFalse );
+ 	iReceiving = ETrue;
+	iSvrSocket.RecvFrom(iIncomingMsgDataPtr, iDHCPClientAddr, 0, *aStatus);
+	return static_cast<CDHCPState*>(iActiveEvent);
+	}
+	
+void CDHCPIP4StateMachine::PrepareToSendServerMsgL( CDHCPStateMachine::EAddressType aEAddressType)
+/**
+  * PrepareToSendServerMsgL
+  *
+  * This function is called to set the correct destination address
+  * for messages before they are sent.
+  *
+  * @internalTechnology
+  */	
+	{
+	// nothing is done with iClientId in server implementation
+	// but it is passed to reuse the existing function.
+	DhcpMessage()->FinishL(iClientId); 
+	DhcpMessage()->Dump();
+	if (aEAddressType==EUnicast)
+		{
+		if(iBroadCastFlag)
+			{
+			__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::SetDestination - broadcast")));
+			iDHCPClientAddr.SetV4MappedAddress(KInetAddrBroadcast);		
+			}
+		else
+			{
+			__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::SetDestination - unicast")));
+			iDHCPClientAddr.SetV4MappedAddress(iYiaddr);// client ip address
+			}
+		}
+	else
+		{
+		__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::SetDestination - broadcast")));
+		iDHCPClientAddr.SetV4MappedAddress(KInetAddrBroadcast);	
+		}
+
+// While DHCP server listens on a custom port, the server message for client
+// needs to be the custom server port + 1 and not the default client port (i.e., 68)
+#ifdef _DEBUG
+	iDHCPClientAddr.SetPort(GetDestPort()+1);
+#else
+	iDHCPClientAddr.SetPort(KDhcpClientPort);
+#endif
+	}
+	
+void CDHCPIP4StateMachine::GetClientAddress( TInetAddr& aAddress )
+/**
+  * GetClientAddress
+  *
+  * Gets the assigned client address
+  *
+  * @internalTechnology	
+*/
+	{
+	aAddress = iDHCPClientAddr;
+	}
+
+TUint32 CDHCPIP4StateMachine::GenerateClientIPAddress()
+/**
+  * GenerateClientIPAddress
+  *
+  * Generate valid IP address to be offered to the client
+  *
+  *@internalTechnology	
+*/
+	{
+	// get the server IP address	
+	TUint32 serverAddr = iCurrentAddress.Address();
+	TUint32 hostId = (serverAddr & ~KInetAddrNetMaskC) + 1;
+	if (hostId >= 255)
+	 {
+	 hostId = 1;
+	 }
+	return (serverAddr & KInetAddrNetMaskC) | hostId;
+	}
+	
+void CDHCPIP4StateMachine::SetMessageHeaderAsServerL( TDHCPv4MessageType aMsgType )
+/**
+  * SetMessageHeaderAsServerL
+  *
+  * Fills in the DHCP header information to be sent to the client
+  *
+  * @internalTechnology
+  */
+	{
+	TTime now;
+	TTimeIntervalSeconds secs;
+	now.HomeTime();	
+	(void)now.SecondsFrom(iTaskStartedAt, secs);
+
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	v4Msg->InitialiseL();
+	v4Msg->SetSecs(static_cast<TUint16>(secs.Int()));	// time field is 16 bits, time elapsed will be less than 16 bits, hence no data loss
+	v4Msg->SetXid(iXid.Xid());
+	// set to indicate we are using DHCP server implementation
+	v4Msg->iDHCPServerImpl = ETrue; 
+	v4Msg->SetCIAddr(iCiaddr);
+	// +++++++++++++++++++++ Message Type (1 byte) ++++++++++++++++++++++++++++++++/
+	v4Msg->AddOptionL(EDHCPMessageType, 1)->SetBigEndian(aMsgType);
+	
+	switch(aMsgType)
+		{
+		case EDHCPOffer:
+		case EDHCPAck:
+			// ++++++++Subnet mask, Router and Server IP set with server address ++++++++++/			
+			v4Msg->AddOptionL(EDHCPSubnetMask,KIp4AddrByteLength)->SetBigEndian(KInetAddrNetMaskC); // 255.255.255.0
+			v4Msg->AddOptionL(EDHCPRouter,KIp4AddrByteLength)->SetBigEndian(iCurrentAddress.Address());
+			v4Msg->AddOptionL(EDHCPServerID,KIp4AddrByteLength)->SetBigEndian(iCurrentAddress.Address());	
+			break;
+
+		case EDHCPNak:
+			// ++++++++Server IP set with server address ++++++++++/
+			v4Msg->AddOptionL(EDHCPServerID,KIp4AddrByteLength)->SetBigEndian(iCurrentAddress.Address());	
+			break;
+		}
+	
+	TUint8 htype,hlen;
+	//  fill in something "traditional" so as not to upset a stupid server.
+	//  This is a best guess based on lack of specs in this area
+	htype = 1; // ethernet
+	hlen = 6; // mac address length
+	v4Msg->SetCHAddr(iClientHWAddr);
+
+	v4Msg->SetHeader(EDHCPBootReply,  htype /*hardware addr type*/,  hlen /*hardware addr length*/,  0 /*hops*/);
+	v4Msg->SetFlags(iFlag);
+#ifdef _DEBUG
+	if (CDHCPServer::DebugFlags() & KDHCP_RequestIP4BroadcastOffer)
+		{
+		v4Msg->SetFlags(0x8000); // force broadcast
+		}
+#endif
+	}
+			
+#endif // SYMBIAN_NETWORKING_DHCPSERVER
+
+void CDHCPIP4StateMachine::PrepareToSendL( CDHCPStateMachine::EAddressType aEAddressType )
+/**
+  * PrepareToSendL
+  *
+  * This function is called to set the correct destination address
+  * for messages before they are sent.
+  *
+  * @internalTechnology
+  */	
+	{
+#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+	if (iDhcpInformAckPending)
+		{
+		DhcpMessage()->FinishL(iClientId,&iSavedExtraParameters);
+		}
+	else
+		{
+#endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+	DhcpMessage()->FinishL(iClientId);
+#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+		}	
+#endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+	DhcpMessage()->Dump();
+	if (aEAddressType==EUnicast)
+		{
+		__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::SetDestination - unicast")));
+		iDHCPServerAddr.SetV4MappedAddress(iServerAddress);
+		}
+	else
+		{
+		__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::SetDestination - broadcast")));
+		iDHCPServerAddr.SetV4MappedAddress(KInetAddrBroadcast);	
+		}
+#ifndef _DEBUG
+	iDHCPServerAddr.SetPort(KDhcpDestPort);
+#else
+	// Simulate initialisation, renewal or rebind failure by using the wrong port.
+	if( ( CDHCPServer::DebugFlags() & KDHCP_FailDiscover ) || ( CDHCPServer::DebugFlags() & KDHCP_FailRenew ) || ( CDHCPServer::DebugFlags() & KDHCP_FailRebind ) )
+		{
+		iDHCPServerAddr.SetPort(KDhcpWrongDestPort);
+		}
+	else
+		{
+		iDHCPServerAddr.SetPort(GetDestPort());
+		}
+#endif
+	}
+
+
+void CDHCPIP4StateMachine::AssembleClientIDsL()
+/**
+  * Sets the client id - this just has to be a cookie for the server to use for indexing.
+  * 
+  *   On an addressed link (e.g. ethernet), hardware address type/value pair is a good combo to use
+  *      as it mirrors a few other popular implementations..
+  */
+	{
+    FetchHWAddress();
+
+    iClientId.CreateL(KMaxSockAddrSize);
+    iClientId.SetLength(1);		// set length to 1 byte
+
+	if(iHardwareAddr.Family()!=KAFUnspec)
+		{
+		// we're on a link with hardware addressing e.g. ethernet
+		__CFLOG_VAR((KLogSubSysDHCP, KLogCode,
+						_L8("CDHCPIP4StateMachine::AssembleClientIDsL - hardware address type=%d, length=%d"),
+						iHardwareAddr.Port(), iHardwareAddr.Length() - KHwAddrOffset));
+
+		iClientId[0] = static_cast<TUint8>(iHardwareAddr.Port());	// fill in the hwAddrType
+	    iClientId.Append(iHardwareAddr.Mid(KHwAddrOffset, iHardwareAddr.Length() - KHwAddrOffset));
+		}
+	else // family was unspecified meaning no hardware address
+    	{
+    	// This means we're on a point-to-point link (i.e. one with no hardware addressing).
+    	//  We'll make client id look like an ethernet/mac address combo to reduce the chance of stupid servers getting upset
+		__CFLOG_VAR((KLogSubSysDHCP, KLogCode,
+						_L8("CDHCPIP4StateMachine::AssembleClientIDsL - no hardware address (suggesting point-to-point)"
+						     " so generating a random 4 byte client id")));
+		iClientId[0] = static_cast<TUint8>(1);	// force hwAddrType to look like ethernet
+    	TUint32 data = Math::Random();
+		iClientId.Append(TPckgC<TUint32>(data));
+		iClientId.Append(TPckgC<TUint16>(data));
+    	}
+	}
+
+
+void CDHCPIP4StateMachine::GetServerAddress( TInetAddr& aAddress )
+{
+	aAddress = iDHCPServerAddr;
+}
+
+
+void CDHCPIP4StateMachine::SetCurrentAddress(const TInetAddr& aCurrentAddress, const TInetAddr& aSubnetMask)
+/**
+  * The SetCurrentAddress function
+  *
+  * Stores ip address and subnet mask and assembles the broadcast address
+  *
+  * @internalTechnology
+  */
+	{
+	iCurrentAddress = aCurrentAddress;
+	iSubnetMask = aSubnetMask;
+	TInetAddr broadcast;
+	broadcast.SubNetBroadcast(iCurrentAddress, iSubnetMask);
+	iBroadcastAddress = broadcast.Address();
+	}
+
+void CDHCPIP4StateMachine::SetMessageHeaderL( TDHCPv4MessageType aMsgType )
+/**
+  * Puts a standard header into the message
+  *
+  * @internalTechnology
+  */
+	{
+	TTime now;
+	TTimeIntervalSeconds secs;
+	now.HomeTime();	
+	(void)now.SecondsFrom(iTaskStartedAt, secs);
+
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	v4Msg->InitialiseL();
+	v4Msg->SetSecs(static_cast<TUint16>(secs.Int()));	// time field is 16 bits, time elapsed will be less than 16 bits, hence no data loss
+	v4Msg->SetXid(iXid.Xid());
+
+	TUint8 htype,hlen;
+	if(iHardwareAddr.Family()!=KAFUnspec)
+		{
+		// we have link layer addressing so fill in the blanks..
+		htype = static_cast<TUint8>(iHardwareAddr.Port()); // hwAddr type (hidden in port field)...there won't be any loss of data
+		hlen = static_cast<TUint8>(iHardwareAddr.Length()-KHwAddrOffset); // length won't be too long that we lose data. Data starts 8 bytes in, thats why length is minus an offset(8)
+		v4Msg->SetCHAddr(iHardwareAddr);
+		}
+	else
+		{
+		// We have no link layer addressing so fill in something "traditional" so as not to upset a stupid server.
+		//  This is a best guess based on lack of specs in this area
+		htype = 1; // ethernet
+		hlen = 6; // mac address length
+		}
+
+	v4Msg->SetHeader(EDHCPBootRequest,  htype /*hardware addr type*/,  hlen /*hardware addr length*/,  0 /*hops*/);
+	v4Msg->SetFlags(0x0000);
+#ifdef _DEBUG
+	if (CDHCPServer::DebugFlags() & KDHCP_RequestIP4BroadcastOffer)
+		{
+		v4Msg->SetFlags(0x8000); // force broadcast
+		}
+#endif
+	// +++++++++++++++++++++ Message Type (1 byte) ++++++++++++++++++++++++++++++++/
+	v4Msg->AddOptionL(EDHCPMessageType, 1)->SetBigEndian(aMsgType);
+	}
+
+
+
+
+TUint8 CDHCPIP4StateMachine::GetMessageTypeL() const
+/**
+  * Returns the message type from the DHCP message
+  * i.e. whether the message is an offer, ack, nak...
+  *
+  * @internalTechnology 
+  */
+	{
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	v4Msg->ParseL();
+	v4Msg->Dump();	
+	
+	return v4Msg->iOptions.GetMessageType();
+	}
+
+TBool CDHCPIP4StateMachine::CheckXid() const
+/**
+  * Checks xid of incoming packet against that of last message sent
+  * must be called after GetMessageType so that message has been parsed!
+  *
+  * @internalTechnology
+  */
+	{
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	// check the Xid matches the xid we put in the discover
+	if (v4Msg->GetXid()!=iXid.Xid())
+		{
+		__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::GetMessageTypeL - non-matching xid")));
+		return EFalse;	// does not match so we are not interested in this message
+		}
+	return ETrue;
+	}
+
+void CDHCPIP4StateMachine::CreateDiscoverMsgL()
+/**
+  * Puts the specifics of the discover message into
+  * the message buffer
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::CreateDiscoverMsgL")));
+	
+	if(iTaskStartedAt == 0)
+		{
+		// set time stamp to now
+		iTaskStartedAt.HomeTime();
+		iMessageSender->SetTaskStartedTime(iTaskStartedAt);
+		}
+	iXid.SetXid(static_cast<TUint32>(iXid.Rnd(0,KMaxTInt)));
+	SetMessageHeaderL(EDHCPDiscover);
+
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	
+	// +++++++++++++++++++++ requested IP address +++++++++++++++++++++++++++++++++/
+	TInetAddr unspAddr;  //creates unspecified address
+	// now check to see if a previous address exists in CommDB with an existing lease
+	if (!iCurrentAddress.Match(unspAddr))
+		{
+		// if we have a known address (perhaps from an expired lease) then request it
+		// an address is 4 bytes long
+		v4Msg->AddOptionL(EDHCPRequestedIPAddr, KIp4AddrByteLength)->SetBigEndian(iCurrentAddress.Address());
+		}
+	// XXX: Add hostname to discover (maybe request), update device hostname
+	// if offered value differs - repeat for IPv6
+	
+	// +++++++++++++++++++++ FQDN update request ++++++++++++++++++++++++++++++++++/
+	CreateFqdnUpdateRequestL();
+	}
+
+void CDHCPIP4StateMachine::CreateOfferAcceptanceRequestMsgL()
+/**
+  * Puts the specifics of the offer acceptance request
+  * message into the message buffer
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::CreateOfferAcceptanceRequestMsgL")));
+	
+	SetMessageHeaderL(EDHCPRequest);
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	
+	// +++++++++++++++++++++ requested IP address +++++++++++++++++++++++++++++++++/
+	v4Msg->AddOptionL(EDHCPRequestedIPAddr, KIp4AddrByteLength)->SetBigEndian(iCurrentAddress.Address());
+	
+	// +++++++++++++++++++++ server ID ++++++++++++++++++++++++++++++++++++++++++++/
+	v4Msg->AddOptionL(EDHCPServerID, KIp4AddrByteLength)->SetBigEndian(iDHCPServerID.Address());
+	
+	// +++++++++++++++++++++ FQDN update request ++++++++++++++++++++++++++++++++++/
+	CreateFqdnUpdateRequestL();	
+	}
+
+
+void CDHCPIP4StateMachine::CreateRebootRequestMsgL()
+/**
+  * Puts the specifics of a reboot request message
+  * into the message buffer 
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::CreateRebootRequestMsgL")));
+	
+	iTaskStartedAt.HomeTime();	// set time stamp to now
+	iMessageSender->SetTaskStartedTime(iTaskStartedAt);
+	iXid.SetXid(static_cast<TUint32>(iXid.Rnd(0,KMaxTInt)));
+	SetMessageHeaderL(EDHCPRequest);
+
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	
+	// +++++++++++++++++++++ requested IP address +++++++++++++++++++++++++++++++++/
+	v4Msg->AddOptionL(EDHCPRequestedIPAddr, KIp4AddrByteLength)->SetBigEndian(iCurrentAddress.Address());
+	}
+
+
+void CDHCPIP4StateMachine::CreateInformMsgL()
+/**
+  * Puts the specifics of an inform message
+  * into the message buffer
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::CreateInformMsgL")));
+	 
+	iXid.SetXid(static_cast<TUint32>(iXid.Rnd(0,KMaxTInt)));
+	iTaskStartedAt.HomeTime();	// set time stamp to now
+	SetMessageHeaderL(EDHCPInform);
+
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	v4Msg->SetCIAddr(iCurrentAddress.Address());
+	//v4Msg->SetFlags(0);		// indicates that the response should be unicast back
+	
+	}
+
+void CDHCPIP4StateMachine::CreateRenewRequestMsgL()
+/**
+  * Puts the specifics of the renew message
+  * into the mesage buffer
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::CreateRenewRequestMsgL")));
+	
+	 if(iTaskStartedAt != 0)
+		{
+		iTaskStartedAt.HomeTime();
+		iMessageSender->SetTaskStartedTime(iTaskStartedAt);
+		}
+	SetMessageHeaderL(EDHCPRequest);
+
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	v4Msg->SetCIAddr(iCurrentAddress.Address());
+	v4Msg->SetFlags(0);		// indicates that the response should be unicast back
+	}	
+
+void CDHCPIP4StateMachine::CreateRebindRequestMsgL()
+/**
+  * Puts the specifics of the rebind message
+  * into the mesage buffer which happened to be the same as the renew message
+  *
+  * @internalTechnology
+  */
+   {
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::CreateRebindRequestMsgL")));
+   CDHCPIP4StateMachine::CreateRenewRequestMsgL(); //to avoid virtual call generation
+   }
+
+void CDHCPIP4StateMachine::CreateReleaseMsgL()
+/**
+  * Puts the specifics of the release message
+  * into the message buffer
+  * 
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::CreateReleaseMsgL")));
+
+	SetMessageHeaderL(EDHCPReleaseMsg);
+	
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	v4Msg->SetCIAddr(iCurrentAddress.Address());
+	v4Msg->SetFlags(0);		// probably don't need to set...as there is no respsonse...
+	
+	// +++++++++++++++++++++ server ID ++++++++++++++++++++++++++++++++++++++++++++/
+	v4Msg->AddOptionL(EDHCPServerID, KIp4AddrByteLength)->SetBigEndian(iDHCPServerID.Address());
+	//remove the configured address ater Completion of the Release Message
+	}
+
+void CDHCPIP4StateMachine::CreateDeclineMsgL()
+/**
+  * Puts the specifics of the decline message
+  * into the message buffer
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::CreateDeclineMsgL")));
+	
+	SetMessageHeaderL(EDHCPDecline);
+
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	
+	// +++++++++++++++++++++ server ID ++++++++++++++++++++++++++++++++++++++++++++/
+	v4Msg->AddOptionL(EDHCPServerID, KIp4AddrByteLength)->SetBigEndian(iDHCPServerID.Address());
+	
+	// +++++++++++++++++++++ requested IP address +++++++++++++++++++++++++++++++++/
+	v4Msg->AddOptionL(EDHCPRequestedIPAddr, KIp4AddrByteLength)->SetBigEndian(iCurrentAddress.Address());
+	RemoveConfiguredAddress();
+	iRetryDhcpIpCount++;
+	}
+
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER
+void CDHCPIP4StateMachine::CreateOfferMsgL()
+/**
+  *  CreateOfferMsgL
+  *
+  * Puts the specifics of the Offer message into the message buffer
+  * 
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::CreateOfferMsgL")));
+
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	iXid.SetXid(v4Msg->GetXid());
+	iTaskStartedAt.HomeTime();
+	// remember the client hardware address from message for later use
+	v4Msg->GetCHAddr(iClientHWAddr);
+	
+	// check if the broadcast flag is set for this client then we sent broadcast message to it
+	TUint16 flags  = v4Msg->GetFlags();
+	if(flags & KBroadCastFlagMask)
+		iBroadCastFlag = ETrue;
+
+	// Create DHCPOFFER message
+	iFlag = 0x8000;			
+	SetMessageHeaderAsServerL(EDHCPOffer);	
+	
+	// generate the client IP addres that is to be offered to the client
+	TUint32 offeredAddress = GenerateClientIPAddress();
+	
+	if(iSvrState == ESvrWaitForAnyDHCPMsgs)
+		{
+		if(iInformClientAddr.Address())
+			v4Msg->SetYIAddr(iInformClientAddr.Address());
+		else
+			v4Msg->SetYIAddr(offeredAddress);
+		}
+	else
+		{
+		v4Msg->SetYIAddr(offeredAddress);
+		}	
+	SetClientIdentified(EFalse);	
+	AddMessageOptionsL();
+	}
+
+void CDHCPIP4StateMachine::HandleInformMsgL()
+/**
+  *  HandleInformMsgL
+  *
+  * Handles DHCPInform message and sends DHCPAck
+  * 
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::CreateResponseMsgL")));
+	
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	
+	iXid.SetXid(v4Msg->GetXid());
+	iTaskStartedAt.HomeTime();
+	
+	v4Msg->GetCHAddr(iClientHWAddr);
+	
+	iCiaddr = v4Msg->GetCIAddr();
+	iYiaddr = v4Msg->GetYIAddr();
+	iFlag = 0x0000;	
+	
+	SetMessageHeaderAsServerL(EDHCPAck);	
+	iYiaddr = iCiaddr;
+	}
+
+void CDHCPIP4StateMachine::CheckClientParamListL()
+	{
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	// check for the Parameter request list option code
+	DHCPv4::COptionNode* pOption = v4Msg->iOptions.FindOption(EDHCPParameterReqList);
+	
+	if(pOption)
+		{
+		TUint8* headerPtr = pOption->Ptr();	
+		
+		// const TUint8 KParamReqTypeOffset = 0; never used
+		const TUint8 KParamReqLengthOffset = 1;
+				
+		//  TUint encoding = headerPtr[KParamReqTypeOffset];   never used
+		TUint length = headerPtr[KParamReqLengthOffset]; // n octets
+	
+		TUint8* bodyPtr = pOption->GetBodyPtr();
+		
+		TUint paramReqAddrOffset;
+		TUint8 paramReqValue;
+		
+		for(TInt i=1; i <= length; i++)
+			{
+			// read the requested parameter list 
+			paramReqAddrOffset = 1 * i;	
+			Mem::Copy(&paramReqValue,(bodyPtr + paramReqAddrOffset),1);  
+			
+			AddParamRequestOptionL(paramReqValue);
+			}
+		}
+	}
+
+void CDHCPIP4StateMachine::AddParamRequestOptionL(TUint8 aParamReqValue)
+	{
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	// default values determined to be used widely are provided by the DHCP server
+	// for these requested parameters
+	
+	// few of the widely requested options are provided, remainning options are ignored
+	switch(aParamReqValue)	
+		{
+	case EDHCPRouter:
+		v4Msg->AddOptionL(EDHCPRouter, KIp4AddrByteLength)->SetBigEndian(iCurrentAddress.Address());	
+		break;
+	case EDHCPBroadcastAddr:
+		v4Msg->AddOptionL(EDHCPBroadcastAddr, KIp4AddrByteLength)->SetBigEndian(KInetAddrBroadcast);	
+		break;	
+	case EDHCPServerID:
+		v4Msg->AddOptionL(EDHCPServerID,KIp4AddrByteLength)->SetBigEndian(iCurrentAddress.Address());	
+		break;
+	case EDHCPSubnetMask:
+		v4Msg->AddOptionL(EDHCPSubnetMask,KIp4AddrByteLength)->SetBigEndian(KInetAddrNetMaskC); 
+		break;	
+	case EDHCPEnd:
+		v4Msg->AddOptionL(EDHCPEnd, 0);
+		break;
+		}
+	}
+
+void CDHCPIP4StateMachine::HandleRequestMsgL()
+/**
+  * CreateRequestResponseMsgL
+  *
+  * Creates DHCPACK or DHCPNAK in response to DHCPREQUEST (Renew, Rebind and Init-Reboot)
+  * 
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::CreateRequestResponseMsgL")));
+	
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	
+	iXid.SetXid(v4Msg->GetXid());
+	iTaskStartedAt.HomeTime();
+	
+	v4Msg->GetCHAddr(iClientHWAddr);
+
+	iCiaddr = v4Msg->GetCIAddr();
+	
+	// check if the broadcast flag is set for this client then we sent broadcast message to it
+	TUint16 flags  = v4Msg->GetFlags();
+	if(flags & KBroadCastFlagMask)
+		iBroadCastFlag = ETrue;
+	 
+	TUint32 offeredAddress = GetIPAddressToOffer();
+		
+	// Check the requested parameter list from client and provide them
+	CheckClientParamListL();
+	
+	TInetAddr reqIPAddress ;
+	reqIPAddress.SetAddress(v4Msg->iOptions.GetRequestedIPAddress());
+				
+	//Check if the message contains the Requested IPAddress 
+	if(reqIPAddress.Address())
+		{
+		//Compare the requested IP Address with the generated offered IP Address.
+		// If same as the offered IP Address,then send DHCPACK
+		if(reqIPAddress.Address() == offeredAddress)
+			{
+			iFlag = 0x8000;			
+			SetMessageHeaderAsServerL(EDHCPAck);
+			iYiaddr = offeredAddress;
+			v4Msg->SetYIAddr(iYiaddr);
+			AddMessageOptionsL();
+			}
+		else
+			{
+			// cannot provide requested IP address
+			iFlag = 0x8000;
+			SetMessageHeaderAsServerL(EDHCPNak);
+			}
+		}
+	else				
+		{
+		// No Requested IP address when DHCPRequest is received during
+		// Renewal and Rebind of IPAddress
+		iFlag = 0x0000;
+		SetMessageHeaderAsServerL(EDHCPAck);
+		iYiaddr = iCiaddr;
+		v4Msg->SetYIAddr(iYiaddr);
+		AddMessageOptionsL();
+	   	}
+	}
+
+TUint32 CDHCPIP4StateMachine::GetIPAddressToOffer()
+	{
+	TUint32 offeredAddress;
+	// check if we ever offered any client which was statically configured
+	// and we responded to DHCPINFORM from it
+	// We offer the same IP address to any second client so that if the first client
+	// existed then the second client fails with DAD
+	if(iSvrState == ESvrWaitForAnyDHCPMsgs)
+		{
+		if(iInformClientAddr.Address())
+			offeredAddress = iInformClientAddr.Address();
+		else 
+			offeredAddress = GenerateClientIPAddress();
+		}
+	else
+		{
+		// Generate a valid IP address which can be offered to the client 
+		offeredAddress = GenerateClientIPAddress();
+		}
+#ifdef SYMBIAN_DNS_PROXY	
+	iOfferedAddress = offeredAddress;
+#endif
+	return offeredAddress;	
+	}
+
+void CDHCPIP4StateMachine::AddMessageOptionsL()
+/**
+  * AddMessageOptionsL
+  *
+  * Adds Lease Time,Renew Time and Rebind Time options
+  * 
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::AddMessageOptionsL")));
+	
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+
+// Providing support for handling custom lease time being set for DHCP server
+// in DEBUG builds using RProperty API's
+	TInt defLeaseTime;
+#ifdef _DEBUG
+	RProperty::Get(KMyPropertyCat, KMyDefaultLeaseTime, defLeaseTime);
+#else
+	defLeaseTime = KDefaultLeaseTime;
+#endif
+	// +++++++++++++++++ Default Fixed Lease Time - 6 hours ++++++++++++++++++++++++++++++++++++++++/
+	v4Msg->AddOptionL(EDHCPLeaseTime, KIp4AddrByteLength)->SetBigEndian(defLeaseTime);
+	// +++++++++++++++++ Renewal Time (T1) - 50% of Lease time ++++++++++++++++++++++++++++++++++++++++/				
+	v4Msg->AddOptionL(EDHCPRenewalT1,KIp4AddrByteLength)->SetBigEndian(defLeaseTime/2);
+	// +++++++++++++++++ Rebind Time (T2) - 75% of Lease time ++++++++++++++++++++++++++++++++++++++++/				
+	v4Msg->AddOptionL(EDHCPRebindT2,KIp4AddrByteLength)->SetBigEndian(defLeaseTime/2+defLeaseTime/4);
+	// These are the options which the client might ask later
+	// Simplified DHCP server is not capable of generating values for these option codes
+	// They will be set later using Ioctl() call
+	v4Msg->AddOptionL(EDHCPNameServer,KIp4AddrByteLength);		
+	v4Msg->AddOptionL(EDHCPSIPServers,KIp4AddrByteLength);		
+		
+	if(!iDNSInformation)
+		{
+		v4Msg->AddOptionL(EDHCPDomainNameServer,KIp4AddrByteLength);
+		
+#ifdef SYMBIAN_DNS_PROXY
+		if(iProxyDnsSrvAddr.Address())		
+		   v4Msg->AddOptionL(EDHCPDomainNameServer,KIp4AddrByteLength)->SetBigEndian(iProxyDnsSrvAddr.Address());
+		if(iProxyDomainName.Length())
+		   v4Msg->AddOptionL(EDHCPDomainName, iProxyDomainName.Length())->GetBodyDes().Copy(iProxyDomainName);
+#endif
+		}
+	else
+		{
+		// point to the option code value in the raw option buffer
+		TPtr8 dnsPtr(const_cast<TUint8*>(iDNSInformation->Ptr()), iDNSInformation->Length(), iDNSInformation->Length());
+		dnsPtr.Set((TUint8*)(dnsPtr.Ptr()+1),dnsPtr.Length()-1,dnsPtr.MaxLength()-1);
+	
+		v4Msg->AddOptionL(EDHCPDomainNameServer,dnsPtr.Length())->GetBodyDes().Copy(dnsPtr);
+		}
+	}
+
+#endif // SYMBIAN_NETWORKING_DHCPSERVER
+	
+TInt CDHCPIP4StateMachine::CreateIPv4LinkLocal()
+/**
+  * Notifies the TCP/IP6 stack whenever the assignment process fails
+  * so that a link local may be created.
+  * 
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG( KLogSubSysDHCP, KLogCode, _L8( "CDHCPIP4StateMachine::CreateIPv4LinkLocal" ) );
+
+	iSocket.Close();	
+	
+	TInt err = iSocket.Open(iEsock, KAfInet, KSockDatagram, KProtocolInetUdp, iConnection);
+	
+	if( err == KErrNone )
+		{
+		// make socket invisible for interface counting
+		(void)iSocket.SetOpt(KSoKeepInterfaceUp, KSolInetIp, 0);
+
+		TPckgBuf<TSoInet6InterfaceInfo> configInfo;
+
+		configInfo().iHwAddr = iHardwareAddr;
+		configInfo().iName = iInterfaceName;
+		configInfo().iDelete = EFalse;
+		configInfo().iAlias = EFalse;
+		configInfo().iDoId = EFalse;
+		configInfo().iState = EIfUp;
+		configInfo().iDoState = ETrue;
+		
+		// zero value better than junk value
+		configInfo().iMtu = 0;
+		configInfo().iSpeedMetric = 0;
+		configInfo().iFeatures = 0; 
+
+		err = iSocket.SetOpt( KSoInetCreateIPv4LLOnInterface, KSolInetIfCtrl, configInfo );
+		}
+		
+	return err;
+	}
+
+void CDHCPIP4StateMachine::HandleOfferL()
+/**
+  * Handles an offer from a dhcp server, providing
+  * an offer of configuration parameters
+  *
+  * @internalTechnology
+  *
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::HandleOffer")));
+	
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	// at this stage just the offered ip address is set into the current address for efficiency
+	iCurrentAddress.SetAddress(v4Msg->GetYIAddr());	
+	
+	TUint32 addr = v4Msg->iOptions.GetServerId();
+	if ( !addr )
+		User::Leave(KErrNotFound);
+	iDHCPServerID.SetAddress(addr);
+	}
+
+CDHCPState* CDHCPIP4StateMachine::HandleReplyL( TRequestStatus* aStatus )
+{
+	iReceiving = EFalse;
+	
+	TInt err = KErrNone;
+
+	if (CheckXid())
+		{
+		switch (GetMessageTypeL())
+			{
+			case EDHCPAck:
+#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS 	
+				if (!iDhcpInformAckPending)
+				{
+#endif//SYMBIAN_NETWORKING_DHCP_MSG_HEADERS	
+				HandleAckL();
+#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS 					
+				}
+#endif//SYMBIAN_NETWORKING_DHCP_MSG_HEADERS	
+
+				break;
+			case EDHCPNak:
+				err = KErrAccessDenied;
+
+				break;
+			default:
+				return ReceiveL(aStatus);
+			}
+		}
+	else
+		{
+		return ReceiveL(aStatus);
+		}
+		
+	User::RequestComplete(aStatus, err);
+	
+	if( err == KErrNone )
+	{
+		return static_cast<CDHCPState*>(iActiveEvent->Next());
+	}
+	
+	return NULL;
+}
+
+void CDHCPIP4StateMachine::HandleAckL()
+/**
+  * Handles an acknowledgement from a dhcp server, storing
+  * configuration parameters and a committed ip address
+  *
+  * @internalTechnology
+  *
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::HandleAck")));
+	
+	if(iRetryDhcpIpCount >= KDHCPv4MaxRetryCount)
+ 	{
+	TPckgBuf<TSoInetInterfaceInfo> opt;
+	TInetAddr addr;
+	while (iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone)
+		{
+	  	if (opt().iName == InterfaceName())
+			{
+		  	addr = opt().iAddress;
+		  	if (addr.IsLinkLocal() && addr.IsV4Compat() )
+		  		{
+		  		RemoveConfiguredAddress(&addr);
+		  		break;
+		  		}
+		  	}
+		}
+	}
+	ConfigureInterfaceL();
+
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	if (!IsUsingStaticAddress())
+		{
+		iRenewalTimeT1 = v4Msg->iOptions.GetRenewalTime();
+		iRebindTimeT2 = v4Msg->iOptions.GetRebindTime();
+		iLeaseTime = v4Msg->iOptions.GetLeaseTime();
+		
+		#ifdef _LOG
+			TBuf<39> addrStr;
+			
+			TInetAddr( v4Msg->GetYIAddr(), 0 ).Output( addrStr );
+			
+			__CFLOG_1( KLogSubSysDHCP, KLogCode, _L( "DHCP server assigned client IP address %S" ), &addrStr );
+		#endif
+		
+#ifdef _DEBUG
+		if (CDHCPServer::DebugFlags() & KDHCP_SetShortLease)
+			{
+			iLeaseTime = KDHCP_ShortLeaseLeaseTime;
+			iRenewalTimeT1 = KDHCP_ShortLeaseRenewTime;
+			iRebindTimeT2 = KDHCP_ShortLeaseRebindTime;
+			CDHCPServer::DebugFlags() &= ~( KDHCP_SetShortLease | KDHCP_SetShortRetryTimeOut );	// we only want this to have an affect the first time...
+			}
+#endif
+		// -- Infinite leases -- INC078424 --
+		//
+		// This block caters for the following 2 cases:
+		//  1. Server sent 0 lease time, meaning "forever". This behaviour wasn't defined in the 
+		//     original RFC but many servers work this way so we need to support it.
+		//  2. Server sent extremely large lease time (e.g. 0xffffffff as specified in RFC).
+		//     As TTimeIntervalSeconds has a maximum of 0x7fffffff, we must enforce this maximum.
+		//
+		if ( iLeaseTime == 0 || iLeaseTime > KReallyLongLease )
+			{
+			iLeaseTime = KReallyLongLease;  // 68 years should be long enough
+			}
+			
+		if (iRenewalTimeT1 == iRebindTimeT2)
+			{
+			// may have only been provided with a lease time...
+			// we need time to renew the lease before it runs out
+			// so we'd better set some times from the overall lease time
+			
+			__CFLOG_VAR((KLogSubSysDHCP, KLogCode,
+				_L8("Invalid Renew/Rebind times received: (RenewT1: %d, RebindT2: %d, Lease: %d)"),
+						iRenewalTimeT1, iRebindTimeT2, iLeaseTime));
+						
+			TUint32 temp = iLeaseTime/4;
+			iRenewalTimeT1=iLeaseTime/2;
+			iRebindTimeT2=iRenewalTimeT1+temp;		
+			
+			__CFLOG_VAR((KLogSubSysDHCP, KLogCode,
+				_L8("New Renew/Rebind Time calculated: (RenewT1: %d, RebindT2: %d)"),
+						iRenewalTimeT1, iRebindTimeT2));	
+						
+			}
+		else if (iRenewalTimeT1<iRebindTimeT2 && iRebindTimeT2<iLeaseTime)
+			{
+			// do nothing as we have got the valid values we were expecting
+			__CFLOG_VAR((KLogSubSysDHCP, KLogCode,
+				_L8("Times received from server: (RenewT1: %d, RebindT2: %d, lease: %d)"),
+						iRenewalTimeT1, iRebindTimeT2, iLeaseTime));
+			}
+		else
+			{
+			__CFLOG_VAR((KLogSubSysDHCP, KLogCode,
+					_L8("HandleAckL Error: invalid times received from server (RenewT1: %d, RebindT2: %d, lease: %d)"),
+							iRenewalTimeT1, iRebindTimeT2, iLeaseTime));
+			User::Leave(KErrArgument);
+			}	
+		
+		}
+
+	delete iHostName;
+	delete iDomainName;
+	iHostName = NULL;
+	iDomainName = NULL;
+
+	v4Msg->iOptions.CopyHostNameL(iHostName);
+	v4Msg->iOptions.CopyDomainNameL(iDomainName);
+	}
+
+#ifdef _DEBUG
+TInt CDHCPIP4StateMachine::GetDestPort()
+	{
+	TInt destPort;
+	User::LeaveIfError(RProperty::Get(KMyPropertyCat, KMyPropertyDestPortv4, destPort));
+	return destPort;
+	}
+#endif
+
+void CDHCPIP4StateMachine::InitialiseSocketL()
+/**
+  * Sets up socket, by opening one associated with the connection
+  * and sets the interface to use for traffic
+  *
+  * @internalTechnology
+  *
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::InitialiseSocketL")));
+	
+	iSocket.Close();
+	
+	User::LeaveIfError(iSocket.Open(iEsock, KAfInet, KSockDatagram, KProtocolInetUdp, iConnection));
+	User::LeaveIfError(iSocket.SetOpt(KSoReuseAddr, KSolInetIp, 1));
+#ifndef _DEBUG
+	User::LeaveIfError(iSocket.SetLocalPort(KDhcpSrcPort));
+#else
+	User::LeaveIfError(iSocket.SetLocalPort(GetDestPort() + 1));
+#endif
+    TInetAddr existingGlobalAddr = this->GetInterfaceGlobalAddress();
+    if( existingGlobalAddr.IsUnspecified() || existingGlobalAddr.IsLinkLocal() )
+    	{
+    	User::LeaveIfError(iSocket.SetOpt(KSoNoSourceAddressSelect, KSolInetIp, 1));
+    	}
+	// make socket invisible for interface counting
+	User::LeaveIfError(iSocket.SetOpt(KSoKeepInterfaceUp, KSolInetIp, 0));
+	
+	TPckgBuf<TSoInetIfQuery> query;
+	query().iName = iInterfaceName;
+	User::LeaveIfError(iSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query));
+	User::LeaveIfError(iSocket.SetOpt(KSoInterfaceIndex, KSolInetIp, query().iIndex));
+	User::LeaveIfError(iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));
+	// loopback of broadcast/multicast packets to the stack is disabled
+	User::LeaveIfError(iSocket.SetOpt(KSoIp6MulticastLoop, KSolInetIp, 0));
+	}
+
+void CDHCPIP4StateMachine::RemoveConfiguredAddress(const TInetAddr * aAddr)
+/**
+  * This function can be called as a result of DAD failing
+  * or the lease expiring! It removes the address from the interface
+  * inside the TCP/IP6 stack as the address cannot continue to be used.
+  *
+  * @see "Implementation of IPv4/IPv6 Basic Socket API for Symbian OS"
+  * document for explanation of TSoInet6InterfaceInfo and its use
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::RemoveConfiguredAddress")));
+	
+	TSoInet6InterfaceInfo interfaceInfo;
+	interfaceInfo.iHwAddr = iHardwareAddr;
+	if(aAddr)
+		{
+		interfaceInfo.iAddress.SetV4MappedAddress(aAddr->Address());
+		interfaceInfo.iState = EIfDown;
+		}
+	else
+		{
+		interfaceInfo.iAddress.SetV4MappedAddress(iCurrentAddress.Address());
+		interfaceInfo.iState = EIfUp;	
+		}
+	interfaceInfo.iDefGate.SetV4MappedAddress(iDefGateway.Address());
+	interfaceInfo.iName = iInterfaceName;
+	interfaceInfo.iDelete = ETrue;
+	interfaceInfo.iAlias = EFalse;
+	interfaceInfo.iDoId = ETrue;
+	
+	interfaceInfo.iDoState = ETrue;
+	interfaceInfo.iDoAnycast = EFalse;
+	
+	// zero value better than junk value
+	interfaceInfo.iMtu = 0;
+	interfaceInfo.iSpeedMetric = 0;
+	interfaceInfo.iFeatures = 0; 
+    CDHCPStateMachine::RemoveConfiguredAddress( interfaceInfo );
+    
+	// Clear the DHCP server address now that we no longer have a lease.
+    iDHCPServerAddr.SetAddress( KInet6AddrNone );
+    //clear the client address & lease time
+   	iCurrentAddress = TInetAddr();
+   	iLeaseTime = 0;
+
+	}
+
+void CDHCPIP4StateMachine::AssignAddresses( TInetAddr& aDest, const TInetAddr& aSrc ) const
+{
+	aDest.SetFamily(KAfInet);
+	aDest.SetAddress(aSrc.Address());
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER
+	if(iServerImpl)
+		{
+// The DHCP server can listen on custom ports
+// Supported only on DEBUG builds
+#ifdef _DEBUG
+		aDest.SetPort(GetDestPort());
+#else
+		aDest.SetPort(KDhcpServerPort);
+#endif
+		}
+	else
+#endif // SYMBIAN_NETWORKING_DHCPSERVER	
+#ifndef _DEBUG
+	aDest.SetPort(KDhcpSrcPort);
+#else
+	{
+	// Simulate initialisation, renewal or rebind failure by using the wrong port.
+	if( ( CDHCPServer::DebugFlags() & KDHCP_FailDiscover ) || ( CDHCPServer::DebugFlags() & KDHCP_FailRenew ) || ( CDHCPServer::DebugFlags() & KDHCP_FailRebind ) )
+		{
+		aDest.SetPort(KDhcpWrongSrcPort);
+		}
+	else
+		{
+		aDest.SetPort(GetDestPort() + 1);
+		}
+	}
+#endif
+	
+}
+
+void CDHCPIP4StateMachine::BindSocketForUnicastL()
+/**
+  * Open a new socket and bind it to the configured source address
+  * ready for a unicast renew message
+  *
+  * @internalTechnology
+  */
+	{
+    __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::BindSocketForRenewL")));
+    iSocket.Close();	// destroy the old socket
+
+    UpdateHistory(CDHCPState::EBindToSource);
+    // Start a new one.
+    User::LeaveIfError(iSocket.Open(iEsock, KAfInet, KSockDatagram, KProtocolInetUdp, iConnection));
+	User::LeaveIfError(iSocket.SetOpt(KSoReuseAddr, KSolInetIp, 1));
+    TInetAddr bindTo;
+    AssignAddresses( bindTo, iCurrentAddress );
+
+    User::LeaveIfError(iSocket.Bind(bindTo));
+
+	// So we can still receive packets from naughty servers who send broadcasts back to 
+	//  unicast requests, we do this:
+	User::LeaveIfError(iSocket.SetOpt(KSoNoSourceAddressSelect, KSolInetIp, 1));
+	User::LeaveIfError(iSocket.SetOpt(KSoUdpAddressSet, KSolInetUdp, 0));
+	// make socket invisable for interface counting
+	User::LeaveIfError(iSocket.SetOpt(KSoKeepInterfaceUp, KSolInetIp, 0));
+	}
+
+void CDHCPIP4StateMachine::ConfigureInterfaceL()
+/**
+  * Set the interface IP address and other params
+  * into the TCP/IP6 stack.
+  *
+  * What we set depends on the setup
+  * in commDB for the service.  If ipAddressFromServer
+  * is true then we set the ip address that has
+  * been assigned by DHCP, along with the netmask and gateway.
+  * If ipAddressFromServer is false, then we set the static ip
+  * address as long as it has been okayed by the DHCP server after
+  * we have sent an inform.  We will then set the netmask and gateway
+  * choosing from those in commDB if they have been given values, or 
+  * those returned in the DHCP Server ACK if a zero address is in commDB
+  * The same principle applies to DNS Server addresses.
+  *
+  * @internalTechnology
+  */
+	{
+
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::ConfigureInterfaceL - Cancel Message Sender")));
+	iMessageSender->Cancel();
+
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::ConfigureInterfaceL - KSoNoSourceAddressSelect")));
+	User::LeaveIfError(iSocket.SetOpt(KSoNoSourceAddressSelect, KSolInetIp, 0));
+
+	TSoInet6InterfaceInfo interfaceInfo;
+	
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+
+	if (!IsUsingStaticAddress())
+		{
+		iCurrentAddress.SetAddress(v4Msg->GetYIAddr());
+		iServerAddress = v4Msg->iOptions.GetServerId();
+		
+		TInetAddr nullAddr;  //creates unspecif. (null) address
+
+		// we want to use CommDb settings if present
+		// but those ifs aren't the solution for that as
+		// these values will potentially fail for renegotiation
+		// for now we should live with this, as there is no time
+		// to change it.
+		if (iSubnetMask.Match(nullAddr))
+			{
+			iSubnetMask.SetAddress(v4Msg->iOptions.GetSubnetMask());
+			}
+
+		if (iBroadcastAddress.Match(nullAddr))
+			{
+			iBroadcastAddress.SetV4MappedAddress(v4Msg->iOptions.GetBroadcastAddress());
+			}
+		
+		if (iDefGateway.Match(nullAddr))
+			{
+			iDefGateway.SetV4MappedAddress(v4Msg->iOptions.GetRouterAddress());
+			}		
+		}
+
+	if( iNameServerAddressesFromServer )
+		{	
+		TInt num = v4Msg->iOptions.NumberOfDomainServers();
+		if (num>0)
+			{
+			iNameServer1.SetAddress(v4Msg->iOptions.GetDomainNameServer(0));
+			if (num>1)
+				{
+				iNameServer2.SetAddress(v4Msg->iOptions.GetDomainNameServer(1));
+				}
+			}
+		}
+
+	
+	interfaceInfo.iHwAddr = iHardwareAddr;
+	interfaceInfo.iAddress.SetV4MappedAddress(iCurrentAddress.Address());
+	interfaceInfo.iNetMask.SetAddress(iSubnetMask.Address());
+	interfaceInfo.iBrdAddr.SetV4MappedAddress(iBroadcastAddress.Address());
+	interfaceInfo.iDefGate.SetV4MappedAddress(iDefGateway.Address());
+	if( iNameServerAddressesFromServer )
+		{
+		interfaceInfo.iNameSer1.SetV4MappedAddress(iNameServer1.Address());
+		interfaceInfo.iNameSer2.SetV4MappedAddress(iNameServer2.Address());	
+		}
+	else
+		{
+		//We need to set the family to KAFUnspec to ensure that the Stack does not overwrite the existing address
+		interfaceInfo.iNameSer1.SetFamily(KAFUnspec);
+		interfaceInfo.iNameSer2.SetFamily(KAFUnspec);
+		}
+	interfaceInfo.iName = iInterfaceName;
+	interfaceInfo.iMtu = 0;
+	interfaceInfo.iSpeedMetric = 0;
+	interfaceInfo.iFeatures = 0; // zero value better than junk value
+	
+	interfaceInfo.iState = EIfUp;
+	
+	interfaceInfo.iDelete = EFalse;
+	interfaceInfo.iAlias = EFalse;
+	interfaceInfo.iDoId = ETrue;
+	interfaceInfo.iDoState = ETrue;
+	interfaceInfo.iDoAnycast = EFalse;
+	interfaceInfo.iDoProxy = EFalse;
+
+	CDHCPStateMachine::ConfigureInterfaceL( interfaceInfo );
+	}
+
+void CDHCPIP4StateMachine::CreateFqdnUpdateRequestL()
+	{	
+#ifndef SYMBIAN_COMMS_REPOSITORY
+	CCommsDatabase* commDb = CCommsDatabase::NewL();
+	CleanupStack::PushL(commDb);
+	
+	CCommsDbTableView* tableView = commDb->OpenViewMatchingUintLC(TPtrC16(NETWORK), TPtrC16(COMMDB_ID), GetNetworkIdL());
+	
+	TDomainName hostName;
+	if (tableView->GotoFirstRecord() == KErrNone)
+		{
+		tableView->ReadTextL(TPtrC16(HOST_NAME), hostName);
+		}
+#else
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+	CMDBSession* session = CMDBSession::NewLC(KCDVersion1_2);
+#else
+	CMDBSession* session = 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.
+	session->SetAttributeMask(ECDHidden | ECDPrivate);
+	
+	CCDNetworkRecord* networkRecord = static_cast<CCDNetworkRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdNetworkRecord));;
+	CleanupStack::PushL(networkRecord);
+	networkRecord->SetRecordId(GetNetworkIdL());
+  	networkRecord->LoadL(*session);
+
+	TDomainName hostName;
+	hostName.Copy(networkRecord->iHostName);
+#endif
+		
+	if (hostName.Length() > 0)
+		{
+		CDnsUpdateOption* dnsUpdateOption = new(ELeave) CDnsUpdateOption();
+		CleanupStack::PushL(dnsUpdateOption);
+		
+		dnsUpdateOption->SetFlag(CDnsUpdateOption::EDnsUpdateFlagE);
+		dnsUpdateOption->SetFlag(CDnsUpdateOption::EDnsUpdateFlagS);
+		dnsUpdateOption->SetDomainName(hostName);
+		
+		RBuf8 optionData;
+		optionData.CleanupClosePushL();
+		
+		dnsUpdateOption->ToStringL(optionData);
+		
+		CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+		COptionNode* optionNode = 
+			v4Msg->AddOptionL(EDHCPDNSUpdate, optionData.Length());
+		
+		optionNode->SetBody(optionData);
+		
+		CleanupStack::PopAndDestroy(&optionData);
+		CleanupStack::PopAndDestroy(dnsUpdateOption);
+		}	
+	
+#ifndef SYMBIAN_COMMS_REPOSITORY
+	CleanupStack::PopAndDestroy(2, commDb);
+#else
+	CleanupStack::PopAndDestroy(2, session);
+#endif
+	}
+	
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER	
+void CDHCPIP4StateMachine::InitialiseServerSocketL()
+/**
+  * Sets up socket, by opening one associated with the connection
+  * and sets the interface to use for traffic
+  *%
+  * @internalTechnology
+  *
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::InitialiseServerSocket")));
+	
+	iSvrSocket.Close();
+	
+	User::LeaveIfError(iSvrSocket.Open(iEsock, KAfInet, KSockDatagram, KProtocolInetUdp, iConnection));
+	User::LeaveIfError(iSvrSocket.SetOpt(KSoReuseAddr, KSolInetIp, 1));
+	
+// The DHCP server can listen on custom ports
+// Supported only on DEBUG builds
+#ifdef _DEBUG
+	User::LeaveIfError(iSvrSocket.SetLocalPort(GetDestPort()));
+#else
+	User::LeaveIfError(iSvrSocket.SetLocalPort(KDhcpServerPort));
+#endif
+	}
+
+	
+void CDHCPIP4StateMachine::InitServerStateMachineL(MStateMachineNotify* aStateMachineNotify)
+/**
+  * Reset the lower state machine for DHCP server implementation.
+  * Set the state machine to wait for client messages on port 67 and 
+  * to handle the messages
+  *
+  * @internalTechnology
+  */
+	{
+	ASSERT(!iFirstState);
+	// after start up wait on port 67 for DHCP client msgs 
+	iFirstState = new(ELeave) CDHCPIP4WaitForClientMsgs(*this);
+	// handle the client messages
+	CDHCPState* handleClientMsg = new(ELeave) CDHCPIP4HandleClientMsgs(*this);
+	iFirstState->SetNext( handleClientMsg);
+	
+	CDHCPStateMachine::Start(aStateMachineNotify);
+	}	
+
+void CDHCPIP4StateMachine::InitServerBinding(MStateMachineNotify* aStateMachineNotify)
+/**
+  * 
+  *
+  * @internalTechnology
+  */
+	{
+	ASSERT(!iFirstState);
+	// binds the server with the static IP address from Comms database
+	iFirstState = new(ELeave) CDHCPIP4BindServer(*this);
+
+	CDHCPStateMachine::Start(aStateMachineNotify);
+	}	
+
+
+void CDHCPIP4StateMachine::ProcessDiscoverL()
+/** Set the state machine to handle discover message using lower state machine
+  * discover-> offer -> request -> ack
+  *  
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::ProcessDiscoverL()")));
+	
+	// the active state was to handle the client message - here Discover message
+	CDHCPState* handleDiscoverMsg = static_cast<CDHCPState*>(iActiveEvent); 
+
+#ifdef SYMBIAN_DNS_PROXY
+	HBufC8*   hostName = HBufC8::NewLC(KMaxName);
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	v4Msg->iOptions.CopyHostNameL(hostName);
+	iClientHostName.Copy(hostName->Des());
+	CleanupStack::PopAndDestroy(hostName);
+#endif // SYMBIAN_DNS_PROXY	
+	
+	CDHCPState* provideOffer = new(ELeave) CDHCPIP4ProvideOffer(*this);
+    handleDiscoverMsg->SetNext( provideOffer );
+    			
+    CDHCPState* sendRequestResponse = new(ELeave) CDHCPIP4SendRequestResponse(*this);
+    provideOffer->SetNext( sendRequestResponse );
+    		
+    iSvrSpecificState = ESvrDiscoverInProgress;
+	}
+	
+void CDHCPIP4StateMachine::ProcessInformL()
+/** Set the state machine to handle inform message using lower state machine
+  * inform -> ack
+  *  
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::ProcessInformL()")));
+
+#ifdef SYMBIAN_DNS_PROXY
+	ReadDhcpMsgParamsL();
+#endif // SYMBIAN_DNS_PROXY		
+	
+	CDHCPState* handleInformMsg = static_cast<CDHCPState*>(iActiveEvent); 
+				
+	CDHCPState* sendInformResponse = new(ELeave) CDHCPIP4SendInformResponse(*this);
+	handleInformMsg->SetNext(sendInformResponse);
+		    
+	iSvrSpecificState = ESvrInformInProgress;
+	}
+    
+void CDHCPIP4StateMachine::ProcessRequestL()
+/** Set the state machine to handle Request message using lower state machine
+  * Request -> Ack / Nak
+  *  
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::ProcessRequestL()")));
+		
+	CDHCPState* handleRequestMsg = static_cast<CDHCPState*>(iActiveEvent); 
+
+	CDHCPState* sendRequestResponse = new(ELeave) CDHCPIP4SendRequestResponse(*this);
+    handleRequestMsg->SetNext(sendRequestResponse);
+		    
+    iSvrSpecificState = ESvrRenewInProgress;
+	}
+			
+
+void CDHCPIP4StateMachine::CheckClientMsgL()
+	{
+	switch(GetClientMessageTypeL())
+		{
+		case EDHCPDiscover:
+			ProcessDiscoverL();
+	    	break;
+    	
+		case EDHCPInform:
+			if(iSvrState != ESvrWaitForAnyDHCPMsgs)
+				{
+				ProcessInformL();
+				}
+  			break;
+  		
+		case EDHCPRequest:
+			ProcessRequestL();
+			break;
+
+		case EDHCPReleaseMsg:
+#ifdef SYMBIAN_DNS_PROXY
+			ReadDhcpMsgParamsL();
+#endif // SYMBIAN_DNS_PROXY
+			iSvrSpecificState = ESvrReleaseInProgress;
+			break;
+
+    	case EDHCPDecline:
+#ifdef SYMBIAN_DNS_PROXY
+			ReadDhcpMsgParamsL();
+#endif // SYMBIAN_DNS_PROXY
+    		iSvrSpecificState = ESvrDeclineInProgress;
+			break;
+		}
+	}
+	
+#ifdef SYMBIAN_DNS_PROXY
+void CDHCPIP4StateMachine::ReadDhcpMsgParamsL()
+	{
+	HBufC8*   hostName = HBufC8::NewLC(KMaxName);
+	CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+	TUint32 staticAddr = v4Msg->GetCIAddr();
+	iClientStaticAddr.SetAddress(staticAddr);
+	v4Msg->iOptions.CopyHostNameL(hostName);
+	iClientHostName.FillZ();
+	iClientHostName.Copy(hostName->Des());
+	CleanupStack::PopAndDestroy(hostName);
+	}
+#endif // SYMBIAN_DNS_PROXY
+#ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION
+TBool CDHCPIP4StateMachine::ClientHwAddrProvisioned()
+	{
+/** DHCP server server checks in which mode it has to offer the IP to clients.
+  * 1. If no HW address is provisioned, don't provide IP to any client.
+  * 2. Provide IP for any client if the DHCP server has already received the MAC as 0xFFFFFFFFFFFF through IOCTL call.
+  * 3. Provide IP for only clients whose MAC address is provisioned using the IOCTL call.
+  * 4. Reset the HW address list if DHCP server receives HW address as 0x000000000000
+  *  
+  * @internalTechnology
+  * @return - ETrue if the client is eligible to get the IP, otherwise EFalse.
+  */
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::ClientHwAddrProvisioned()")));
+	if(iDhcpHwAddrManager->IsHwAddressProvisioned())
+		{
+		if(iDhcpHwAddrManager->IsAnyClientAllowed())
+			{
+			__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("DHCP server assigns IP without MAC provisioning")));
+				return ETrue;
+			}
+		else
+			{
+			Uint64 clientHwAddress = 0;
+			TSockAddr hwAddr;
+			CDHCPMessageHeaderIP4* v4Msg = DhcpMessage();
+			v4Msg->GetCHAddr(hwAddr);
+			TPtrC8 hwAddrPtr(hwAddr.Mid(KHwAddrOffset, KHwAddrLength));
+			TInt index = 0;
+			TInt length = hwAddrPtr.Length();
+			//Convert buffer data to Uint64
+			for(; index < length; index++)
+				{
+				clientHwAddress <<= 8;
+				clientHwAddress += hwAddrPtr[index];
+				}
+			//Check the received MAC address is provisioned. If true provide the DHCP OFFER.
+			//Otherwise go back to wait for any DHCP client messages state
+			if(iDhcpHwAddrManager->Provisioned(clientHwAddress))
+				{
+				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("Client Harware address provisioned")));
+				return ETrue;
+				}
+			}
+		}
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("Client Harware address not provisioned")));
+	return EFalse;
+	}
+#endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION
+#endif // SYMBIAN_NETWORKING_DHCPSERVER