--- /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
+ }
+
+