--- /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(¶mReqValue,(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