tcpiputils/dhcp/src/DHCPIP4Msg.cpp
changeset 0 af10295192d8
child 53 7e41d162e158
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcpiputils/dhcp/src/DHCPIP4Msg.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,640 @@
+// 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 DHCPv4 Message format
+// 
+//
+
+/**
+ @file DHCPIP4Msg.cpp
+ @internalTechnology
+*/
+
+#include "DHCPIP4Msg.h"
+#include "DHCP_Std.h"
+
+using namespace DHCPv4;
+
+COptionNode::~COptionNode()
+	{
+	delete iNext;
+	}
+
+struct SOptionHeader
+	{
+	TInt iCode;
+	TInt iExpLength; // length of the payload of the option in case the payload has a fixed length
+	TInt iAlignment; // alignment of the payload
+	TInt iMinLength; // length of the whole option (including code & length i present)
+#ifdef __FLOG_ACTIVE
+	const TText8* iName;
+#endif
+	};
+
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER
+	#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+	const TInt KNumberOfSupportedOptions = 20;
+	#else 
+const TInt KNumberOfSupportedOptions = 17;
+	#endif
+#else
+	#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+	const TInt KNumberOfSupportedOptions = 19;
+	#else
+const TInt KNumberOfSupportedOptions = 16;
+	#endif
+#endif 
+#ifdef __FLOG_ACTIVE
+const SOptionHeader KOptions[KNumberOfSupportedOptions]= 
+	{   //iCode,           iExpLength, iAlignment, iMinLength iName
+		{EDHCPSubnetMask,       4,       1,          6,       _S8( "EDHCPSubnetMask" )}, //must be the first option
+		{EDHCPRouter,           0,       4,          6,       _S8( "EDHCPRouter" )},
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER		
+		{EDHCPNameServer, 		0,       4,          6,       _S8( "EDHCPNameServer" )},
+#endif // #ifdef SYMBIAN_NETWORKING_DHCPSERVER		
+		{EDHCPDomainNameServer, 0,       4,          6,       _S8( "EDHCPDomainNameServer" )},
+		{EDHCPHostName,         0,       1,          3,       _S8( "EDHCPHostName" )},
+		{EDHCPDomainName,       0,       1,          3,       _S8( "EDHCPDomainName" )},
+		{EDHCPBroadcastAddr,    4,       4,          6,       _S8( "EDHCPBroadcastAddr" )},
+		{EDHCPRequestedIPAddr,  4,       4,          6,       _S8( "EDHCPRequestedIPAddr" )},
+		{EDHCPLeaseTime,        4,       4,          6,       _S8( "EDHCPLeaseTime" )},
+		{EDHCPMessageType,      1,       1,          3,       _S8( "EDHCPMessageType" )},
+		{EDHCPServerID,         4,       4,          6,       _S8( "EDHCPServerID" )},
+		{EDHCPParameterReqList, 0,       1,          3,       _S8( "EDHCPParameterReqList" )},
+		{EDHCPMaxMsgSize,       2,       2,          4,       _S8( "EDHCPMaxMsgSize" )},
+		{EDHCPRenewalT1,        4,       4,          6,       _S8( "EDHCPRenewalT1" )},
+		{EDHCPRebindT2,         4,       4,          6,       _S8( "EDHCPRebindT2" )},
+//		{EDHCPAuthentication,   0,       1,          12,      _S8( "EDHCPAuthentication" )}, not yet
+		{EDHCPSIPServers,		0,		 1,			 3,		  _S8( "EDHCPSIPServers" )},
+#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+		{EDHCPTftpServerName,   0,		 1,			 3,       _S8( "EDHCPTftpServerName")},
+		{EDHCPOptionOverload,   0,		 1,			 3,       _S8( "EDHCPOptionOverload")},
+		{EDHCPTftpServers,		0,		 1,			 3,		  _S8( "EDHCPTftpServers" )},
+#endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+		{EDHCPClientID,         0,       1,          4,       _S8( "EDHCPClientID" )}
+	};
+
+void COptionNode::Dump(const TDesC& aTag, const TDesC& aFile)
+	{
+	RFileLogger f;
+	if (f.Connect() == KErrNone)
+		{
+		f.CreateLog(aTag, aFile, EFileLoggingModeAppend);
+		TInt i = 0;
+		while (KOptions[i].iCode != OpCode() && ++i < KNumberOfSupportedOptions){/*do nothing*/}
+		
+		TInt n = iPtr8[1];
+		if (i < KNumberOfSupportedOptions)
+			{
+			f.WriteFormat(_L8("Option Code: %s, length: %d"), KOptions[i].iName, n);
+			}
+		else
+			{
+			f.WriteFormat(_L( "Option Code: %d, length %d" ), OpCode(), n );
+			}
+		if (GetItemLength() > 2)
+			{
+			f.HexDump(NULL, NULL, GetBodyPtr(), GetLength());
+			}
+		f.CloseLog();
+		f.Close();
+		}
+	}
+#else
+const SOptionHeader KOptions[KNumberOfSupportedOptions]= 
+	{   //iCode,           iExpLength, iAlignment, iMinLength 
+		{EDHCPSubnetMask,       4,       1,          6}, //must be the first option
+		{EDHCPRouter,           0,       4,          6},
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER		
+		{EDHCPNameServer, 		0,       4,          6},
+#endif 	//  SYMBIAN_NETWORKING_DHCPSERVER	
+		{EDHCPDomainNameServer, 0,       4,          6},
+		{EDHCPHostName,         0,       1,          3},
+		{EDHCPDomainName,       0,       1,          3},
+		{EDHCPBroadcastAddr,    4,       4,          6},
+		{EDHCPRequestedIPAddr,  4,       4,          6},
+		{EDHCPLeaseTime,        4,       4,          6},
+		{EDHCPMessageType,      1,       1,          3},
+		{EDHCPServerID,         4,       4,          6},
+		{EDHCPParameterReqList, 0,       1,          3},
+		{EDHCPMaxMsgSize,       2,       2,          4},
+		{EDHCPRenewalT1,        4,       4,          6},
+		{EDHCPRebindT2,         4,       4,          6},
+		{EDHCPClientID,         0,       1,          4},
+#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+		{EDHCPTftpServerName,   0,		 1,			 3},
+		{EDHCPOptionOverload,   0,		 1,			 3},
+		{EDHCPTftpServers,		0,		1,			3},
+#endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+		{EDHCPSIPServers,		0,		1,			3}
+	};
+#endif
+
+void COptionList::ParseL(TPtr8& aDes8)
+/**
+  * Parse message to set pointers into descriptor buffer
+  * at locations of each option supplied in a response msg
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL")));
+	ASSERT(!iRecord.iFirst);
+
+	COptionNode** ppNode = reinterpret_cast<COptionNode**>(&iRecord.iFirst);
+	TUint8 nCode = *aDes8.Ptr();
+	COptionNode* pNode;
+	TInt i, nItemLen, nHeaderLength;
+	while (nCode != EDHCPEnd && aDes8.Length() > 0)
+		{
+		for (i = 0; KOptions[i].iCode != nCode && ++i < KNumberOfSupportedOptions;) {}
+		nHeaderLength = (nCode == EDHCPPad) ? KEDHCPPadLength : KOptionHeaderLength; 
+		pNode = new(ELeave) COptionNode(nHeaderLength);
+		
+		/* ppNode is a pointer to a pointer. It has not got assigned any dynamically allocated memory. But coverity has misinterpreted it an issue.*/
+		// coverity [SYMBIAN.CLEANUP STACK]
+		// coverity [leave_without_push]
+		CleanupStack::PushL(pNode);
+		
+		/* pNode can not be Null here as the memmory assignment is done using new(ELeave). Thus, there is no need of checking for Null, explicitly .*/
+		// coverity[deref_ptr_in_call]	
+		pNode->ParseL(aDes8);
+		nItemLen = pNode->GetItemLength();
+		
+		if (aDes8.Length() > 0)
+			{
+			nCode = *aDes8.Ptr();
+			}
+		else
+			{
+			__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL Option list ended without EDHCPEnd flag")));
+			}
+
+		if (i < KNumberOfSupportedOptions)
+			{
+			// now do some sanity checks and leave if bad results
+			TInt nPayloadLength = nItemLen - nHeaderLength;
+			*ppNode = pNode;
+
+			if (nItemLen < KOptions[i].iMinLength)	// min length check
+				{
+				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL BadDescriptor 2")));
+				*ppNode = NULL;
+				User::Leave(KErrBadDescriptor);
+				}
+
+			if (nPayloadLength % KOptions[i].iAlignment != 0)	// alignment check
+				{
+				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL BadDescriptor 3")));
+				*ppNode = NULL;
+				User::Leave(KErrBadDescriptor);
+				}
+
+			if (KOptions[i].iExpLength > 0 && nPayloadLength != KOptions[i].iExpLength)	//expected length check
+				{
+				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL BadDescriptor 4")));
+				*ppNode = NULL;
+				User::Leave(KErrBadDescriptor);
+				}
+
+			ppNode = reinterpret_cast<COptionNode**>(&(pNode->iNext));
+			CleanupStack::Pop(pNode);
+			}
+		else
+			{
+#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+			//make sure we parse everything becz we support every option now
+			if (pNode)
+				{
+				*ppNode = pNode;
+				ppNode = reinterpret_cast<COptionNode**>(&(pNode->iNext));
+				CleanupStack::Pop(pNode);
+				}
+			else
+				{
+#endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+ 			__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL Code Not Found")));
+
+			/* ppNode is a pointer to a pointer. It has not got assigned any dynamically allocated memory. But coverity has misinterpreted it an issue.*/
+			// coverity [SYMBIAN.CLEANUP STACK]
+			// coverity [memory_leak]
+ 			CleanupStack::PopAndDestroy(pNode);
+ 			pNode=NULL;
+#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+				}
+#endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+			}
+		}
+
+
+	}
+
+COptionNode* COptionList::AddNodeL(TInt aInitialLength, TInt aHeaderLength)
+/**
+  * Create a new node for an option in the message
+  *
+  * @internalTechnology
+  */
+	{
+	COptionNode* pNode = new(ELeave) COptionNode(aHeaderLength);
+	AddNode(pNode);
+	pNode->Header().SetInitialValue(aInitialLength);
+	return pNode;
+	}
+
+COptionNode* COptionList::FindOption(TUint8 aOpCode) const
+/**
+  * Find the location of an option in the message and return a pointer to it
+  *
+  * @internalTechnology
+  */
+	{
+	COptionNode* pNode = static_cast<COptionNode*>(iRecord.iFirst);
+	while (pNode && pNode->OpCode() != aOpCode)
+		{
+		pNode = static_cast<COptionNode*>(pNode->iNext);
+		}
+	return pNode;
+	}
+
+TInt COptionList::NumberOfItemsInAddressListOption(TUint8 aOpCode) const
+/**
+  * Return the number of addresses
+  * from the specified server option.
+  *
+  * @internalTechnology
+  */
+	{
+	COptionNode* pNode = FindOption(aOpCode);
+	return pNode ? pNode->GetLength()/KIp4AddrByteLength : 0;
+	}
+
+TUint32 COptionList::GetAddressFromAddressListOption(TUint8 aOpCode,TInt aPos) const
+/**
+  * Return the address at position aPos in the specified server option code
+  * in TUint32 format.
+  *
+  * @param aPos Indicates which one of the addresses in the list to return
+  * @return TUint32 The address 
+  *
+  * @internalTechnology
+  */
+	{
+ 	COptionNode* pNode = FindOption(aOpCode);
+	return pNode ? BigEndian::Get32(pNode->GetBodyPtr() + aPos * KIp4AddrByteLength) : 0;
+	}
+
+
+TUint32 COptionList::GetValueBigEndian(TUint8 aOpCode) const
+/**
+  * Return a value from the message in big endian format
+  *
+  * @internalTechnology
+  */
+	{
+	COptionNode* pNode = FindOption(aOpCode);
+	return pNode ? pNode->GetBigEndian() : 0;
+	}
+
+TInt COptionList::NumberOfDomainServers() const
+/**
+  * Return the number of domain name server addresses
+  * from the domain name server option.  There are
+  * expected to be more than one.
+  *
+  * @internalTechnology
+  */
+	{
+	return NumberOfItemsInAddressListOption(EDHCPDomainNameServer);
+	}
+
+TUint32 COptionList::GetDomainNameServer(TInt aPos) const
+/**
+  * Return the domain name server address at position aPos
+  * in TUint32 format.
+  *
+  * @param aPos Indicates which one of the domain name server addresses to return
+  * @return TUint32 The address of the domain name server
+  *
+  * @internalTechnology
+  */
+	{
+	return GetAddressFromAddressListOption(EDHCPDomainNameServer,aPos);
+	}
+
+
+
+TBool COptionList::CopyHostNameL(HBufC8*& aBuf8) const
+/**
+  * Return a copy of the host name given in the message
+  *
+  * @param aBuf8 A descriptor for the host name to be written into
+  * @return TBool If the copy was successful or not 
+  *
+  * @internalTechnology
+  */
+	{
+	COptionNode* pNode = FindOption(EDHCPHostName);
+	if (pNode)
+		{
+		pNode->CopyBodyToL(aBuf8);
+		}
+	return pNode != NULL;
+	}
+
+TBool COptionList::CopyDomainNameL(HBufC8*& aBuf8) const
+/**
+  * Return a copy of the domain name given in the message 
+  *
+  * @param aBuf8 A descriptor for the domain name to be written into
+  * @return TBool If the copy was successful or not 
+  */
+	{
+	COptionNode* pNode = FindOption(EDHCPDomainName);
+	if (pNode)
+		{
+		pNode->CopyBodyToL(aBuf8);
+		}
+	return pNode != NULL;
+	}
+
+CDHCPMessageHeaderIP4::CDHCPMessageHeaderIP4(HBufC8*& aMsg) :
+	CDHCPMessageHeader(&iXid, 4, aMsg), //|     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
+		iXid(&iSecs, 4), iSecs(&iFlags, 2), iFlags(&iCiaddr, 2),
+		iCiaddr(&iYiaddr, 4), iYiaddr(&iSiaddr, 4), iSiaddr(&iGiaddr, 4),
+		iGiaddr(&iChaddr, 4), iChaddr(&iSname, 16), iSname(&iFile, 64),
+		iFile(&iCookie, 128), iCookie(&iOptions, 4),
+		iOptions(NULL)
+		{
+#ifdef _FLOG_ACTIVE
+		iName = _L("op ht hl ho");
+		iXid.iName = _L("Xid");
+		iSecs.iName = _L("Secs");
+		iFlags.iName = _L("Flags");
+		iCiaddr.iName = _L("Ciaddr");
+		iYiaddr.iName = _L("Yiaddr");
+		iSiaddr.iName = _L("Siaddr");
+		iGiaddr.iName = _L("Giaddr");
+		iChaddr.iName = _L("Chaddr");
+		iSname.iName = _L("Sname");
+		iFile.iName = _L("File");
+		iCookie.iName = _L("Cookie");
+#endif
+		}
+	
+CDHCPMessageHeaderIP4::~CDHCPMessageHeaderIP4()
+	{
+	Close();
+	}
+
+COptionNode* CDHCPMessageHeaderIP4::AddOptionL(TDHCPOptionCodes aOpCode, TInt aLength)
+/**
+  * First stage of adding an option to the message. Calls AddNode to create space
+  * for message.
+  *
+  * @param aOpCode The opcode of the options to be added
+  * @param aLength The length of the option data
+  * @return COptionNode* The pointer to the option in the message
+  *
+  @ @internalTechnology
+  */
+	{
+	COptionNode* pNode = iOptions.AddNodeL(aLength, aLength > 0 ? KOptionHeaderLength : 1);
+	TPtr8 ptr = iMsg->Des();
+	pNode->InitialiseL(ptr);
+	pNode->SetOpCode(static_cast<TUint8>(aOpCode));
+	return pNode;
+	}
+
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER
+void CDHCPMessageHeaderIP4::ParseClientMsgL()
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPMessageHeaderIP4::ParseL")));
+	
+	TPtr8 ptr = iMsg->Des();
+	iRecord.ParseL(ptr);
+	// now it is parsed, first check whether this is actually a REPLY message from a DHCP Server...
+	if (GetOpCode() != EDHCPBootRequest)
+		{
+		User::Leave(KErrNotFound);
+		}
+	}	
+
+void CDHCPMessageHeaderIP4::GetCHAddr(TSockAddr& aSockAddr) 
+/**
+  * Retrieve Your IP Address from message
+  *
+  * @internalTechnology  *
+  */
+	{
+	aSockAddr.SetFamily(KAFUnspec);
+	aSockAddr.SetLength(KHwAddrOffset);
+	aSockAddr.Append(iChaddr.GetBodyDes());
+	}	
+#ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION
+void CDHCPMessageHeaderIP4::GetClientHwAddr(TSockAddr& aSockAddr) 
+	{
+/**
+  * Return the Client Hardware Address.
+  *
+  * @internalTechnology
+  */
+	aSockAddr.Append(iChaddr.GetBodyDes());
+	}
+#endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION
+#endif // SYMBIAN_NETWORKING_DHCPSERVER		
+	
+#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+void CDHCPMessageHeaderIP4::FinishL(TDesC8& aClientId, const TDesC8* aOptionsPtr)
+/**
+  * Put finishing touches to message for sending. Mainly used for sending DHCPINFORM message 
+  * Puts the requested parameter list to 'Parameter Request List' 
+  * If aFlag is set to TRUE, then all parameters have to requested including default parameters+extra requested parameters
+  * Basically copies in the magic cookie (99.130.83.99)
+  * and the end marker then set the length of the descriptor
+  * as we have been pushing data into the descriptor manually
+  *
+  * @see RFC 2131 for explanation of the magic cookie!
+  * @param aClientId The client ID string to be added to the message
+  * @param aOptionsPtr Contains a list of opcodes to be sent in the parameter list of the DHCPINFORM message
+  *
+  * @internalTechnology
+  */
+#else 
+void CDHCPMessageHeaderIP4::FinishL(TDesC8& aClientId)
+/**
+  * Put finishing touches to message for sending
+  * Basically copies in the magic cookie (99.130.83.99)
+  * and the end marker then set the length of the descriptor
+  * as we have been pushing data into the descriptor manually
+  *
+  * @param aClientId The client ID string to be added to the message
+  * @see RFC 2131 for explanation of the magic cookie!
+  *
+  * @internalTechnology
+  */
+#endif //SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPMessageBase::FinishL")));
+	
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER
+	if(!iDHCPServerImpl)
+	{
+#endif // SYMBIAN_NETWORKING_DHCPSERVER	
+	
+	TUint8 reqListArray[KDhcpParameterRequestListLen] = {EDHCPHostName, EDHCPDomainNameServer, 
+							EDHCPDomainName, EDHCPSubnetMask, EDHCPRouter, EDHCPBroadcastAddr, EDHCPSIPServers};
+	TPtr8 ptr(reqListArray, KDhcpParameterRequestListLen, KDhcpParameterRequestListLen);
+	
+	// +++++++++++++++++++++++ Client ID +++++++++++++++++++++++++++++++++++++++++/
+	AddOptionL(EDHCPClientID, aClientId.Length())->GetBodyDes().Copy(aClientId);
+		
+#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+	RBuf8 appendOpCodeList;
+	appendOpCodeList.CreateL(ptr);
+	if (aOptionsPtr)
+		{
+		TInt optLen=aOptionsPtr->Length();
+		appendOpCodeList.ReAllocL(KDhcpParameterRequestListLen+optLen);
+		appendOpCodeList.Append(aOptionsPtr->Ptr(),optLen);
+		}
+	AddOptionL(EDHCPParameterReqList, appendOpCodeList.Length())->GetBodyDes().Copy(appendOpCodeList);
+	appendOpCodeList.Close();
+#else
+	// +++++++++++++++++++++++ Parameter Request List ++++++++++++++++++++++++++++/
+	AddOptionL(EDHCPParameterReqList, ptr.Length())->GetBodyDes().Copy(ptr);
+#endif		
+	// +++++++++++++++++++++++ Maximum message size (2 bytes) ++++++++++++++++++++/
+	AddOptionL(EDHCPMaxMsgSize, 2)->SetBigEndian(KDhcpMaxMsgSizeIP4);
+	
+#ifdef SYMBIAN_NETWORKING_DHCPSERVER
+	}
+#endif // SYMBIAN_NETWORKING_DHCPSERVER	
+		
+	TInetAddr magic;
+	_LIT(magicCookie, "99.83.130.99");
+	User::LeaveIfError(magic.Input(magicCookie));	// essential the magic cookie is correct
+	iCookie.SetLittleEndian(magic.Address());
+		
+	ASSERT(!iOptions.FindOption(EDHCPEnd));
+	AddOptionL(EDHCPEnd, 0);
+
+   //add padding if msg shorter than 300 bytes
+ 	TInt len=iMsg->Length();
+ 	TPtr8 des=iMsg->Des();
+	if (len<300)
+      {
+		des.AppendFill(EDHCPPad, 300-len);
+      }
+	}
+	
+void CDHCPMessageHeaderIP4::ParseL()
+/**
+  * When a response is received to a message
+  * this function will unpack the response by creating
+  * option objects which can be easily used to retrieve 
+  * the values returned in these options.  Providing 
+  * this functionality hides the nasty descriptor operations. 
+  *
+  * Each option class has a pointer set to the start point
+  * of their data in the response message.
+  *
+  * There is no need to explicitly unpack the mandatory fields
+  * of the DHCP message that has been returned.  Accessor functions
+  * simply extract the data sraight out of the decsriptor.
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPMessageHeaderIP4::ParseL")));
+	
+	TPtr8 ptr = iMsg->Des();
+	iRecord.ParseL(ptr);
+	// now it is parsed, first check whether this is actually a REPLY message from a DHCP Server...
+	if (GetOpCode() != EDHCPBootReply)
+		{
+		User::Leave(KErrNotFound);
+		}
+	}
+	
+	
+void CDHCPMessageHeaderIP4::SetHeader(TUint8 aOpCode,TUint8 aType,TUint8 aLength,TUint8 aHops)
+/**
+  * Sets Op Code in message
+  *
+  * @internalTechnology
+  *
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPMessageHeaderIP4::SetHeader")));
+		
+	TUint8* ptr = &(GetBodyPtr()[0]);
+	*ptr = aOpCode;
+	*++ptr = aType;
+	*++ptr = aLength;
+	*++ptr = aHops;
+	}
+	
+void CDHCPMessageHeaderIP4::SetCHAddr(TSockAddr& aAddr)
+/**
+  * Sets If Hardware Address in message
+  *
+  * @internalTechnology
+  * 
+  */
+	{
+	TUint len = aAddr.Length()-KHwAddrOffset;
+	if(len > KIp4ChAddrMaxLength) { len = KIp4ChAddrMaxLength; }
+	iChaddr.GetBodyDes().Copy(aAddr.Mid(KHwAddrOffset, len));
+	}
+
+void CDnsUpdateOption::ToStringL(RBuf8& aBuf8) const
+/**
+  * Writes DNS update option data to a string suitable for sending out
+  * on to the network
+  *
+  * @internalTechnology
+  * 
+  */
+	{
+	RBuf8 encodedDomainName;
+	encodedDomainName.CleanupClosePushL();
+
+	TDomainNameArray domainNames;
+	CleanupClosePushL(domainNames);
+	domainNames.AppendL(iDomainName);
+
+	CDomainNameCodec* domainNameEncoder = new(ELeave) CDomainNameCodec();
+	CleanupStack::PushL(domainNameEncoder);
+
+
+	domainNameEncoder->EncodeL(domainNames, encodedDomainName);
+
+
+	CleanupStack::PopAndDestroy(domainNameEncoder);
+	CleanupStack::PopAndDestroy(&domainNames); // closes the RBuf8	
+
+
+	aBuf8.Zero();
+
+	aBuf8.ReAllocL( 3 + encodedDomainName.Length() );
+
+	aBuf8.Append((TChar)(iFlags.Value()));
+	aBuf8.Append((TChar)iRCode1);
+	aBuf8.Append((TChar)iRCode2);
+	aBuf8.Append(encodedDomainName);
+
+	CleanupStack::PopAndDestroy(&encodedDomainName); // closes the array
+	}
+
+