tcpiputils/dhcp/src/DHCPIP4Msg.cpp
changeset 0 af10295192d8
child 53 7e41d162e158
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements the DHCPv4 Message format
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file DHCPIP4Msg.cpp
       
    20  @internalTechnology
       
    21 */
       
    22 
       
    23 #include "DHCPIP4Msg.h"
       
    24 #include "DHCP_Std.h"
       
    25 
       
    26 using namespace DHCPv4;
       
    27 
       
    28 COptionNode::~COptionNode()
       
    29 	{
       
    30 	delete iNext;
       
    31 	}
       
    32 
       
    33 struct SOptionHeader
       
    34 	{
       
    35 	TInt iCode;
       
    36 	TInt iExpLength; // length of the payload of the option in case the payload has a fixed length
       
    37 	TInt iAlignment; // alignment of the payload
       
    38 	TInt iMinLength; // length of the whole option (including code & length i present)
       
    39 #ifdef __FLOG_ACTIVE
       
    40 	const TText8* iName;
       
    41 #endif
       
    42 	};
       
    43 
       
    44 #ifdef SYMBIAN_NETWORKING_DHCPSERVER
       
    45 	#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
    46 	const TInt KNumberOfSupportedOptions = 20;
       
    47 	#else 
       
    48 const TInt KNumberOfSupportedOptions = 17;
       
    49 	#endif
       
    50 #else
       
    51 	#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
    52 	const TInt KNumberOfSupportedOptions = 19;
       
    53 	#else
       
    54 const TInt KNumberOfSupportedOptions = 16;
       
    55 	#endif
       
    56 #endif 
       
    57 #ifdef __FLOG_ACTIVE
       
    58 const SOptionHeader KOptions[KNumberOfSupportedOptions]= 
       
    59 	{   //iCode,           iExpLength, iAlignment, iMinLength iName
       
    60 		{EDHCPSubnetMask,       4,       1,          6,       _S8( "EDHCPSubnetMask" )}, //must be the first option
       
    61 		{EDHCPRouter,           0,       4,          6,       _S8( "EDHCPRouter" )},
       
    62 #ifdef SYMBIAN_NETWORKING_DHCPSERVER		
       
    63 		{EDHCPNameServer, 		0,       4,          6,       _S8( "EDHCPNameServer" )},
       
    64 #endif // #ifdef SYMBIAN_NETWORKING_DHCPSERVER		
       
    65 		{EDHCPDomainNameServer, 0,       4,          6,       _S8( "EDHCPDomainNameServer" )},
       
    66 		{EDHCPHostName,         0,       1,          3,       _S8( "EDHCPHostName" )},
       
    67 		{EDHCPDomainName,       0,       1,          3,       _S8( "EDHCPDomainName" )},
       
    68 		{EDHCPBroadcastAddr,    4,       4,          6,       _S8( "EDHCPBroadcastAddr" )},
       
    69 		{EDHCPRequestedIPAddr,  4,       4,          6,       _S8( "EDHCPRequestedIPAddr" )},
       
    70 		{EDHCPLeaseTime,        4,       4,          6,       _S8( "EDHCPLeaseTime" )},
       
    71 		{EDHCPMessageType,      1,       1,          3,       _S8( "EDHCPMessageType" )},
       
    72 		{EDHCPServerID,         4,       4,          6,       _S8( "EDHCPServerID" )},
       
    73 		{EDHCPParameterReqList, 0,       1,          3,       _S8( "EDHCPParameterReqList" )},
       
    74 		{EDHCPMaxMsgSize,       2,       2,          4,       _S8( "EDHCPMaxMsgSize" )},
       
    75 		{EDHCPRenewalT1,        4,       4,          6,       _S8( "EDHCPRenewalT1" )},
       
    76 		{EDHCPRebindT2,         4,       4,          6,       _S8( "EDHCPRebindT2" )},
       
    77 //		{EDHCPAuthentication,   0,       1,          12,      _S8( "EDHCPAuthentication" )}, not yet
       
    78 		{EDHCPSIPServers,		0,		 1,			 3,		  _S8( "EDHCPSIPServers" )},
       
    79 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
    80 		{EDHCPTftpServerName,   0,		 1,			 3,       _S8( "EDHCPTftpServerName")},
       
    81 		{EDHCPOptionOverload,   0,		 1,			 3,       _S8( "EDHCPOptionOverload")},
       
    82 		{EDHCPTftpServers,		0,		 1,			 3,		  _S8( "EDHCPTftpServers" )},
       
    83 #endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
    84 		{EDHCPClientID,         0,       1,          4,       _S8( "EDHCPClientID" )}
       
    85 	};
       
    86 
       
    87 void COptionNode::Dump(const TDesC& aTag, const TDesC& aFile)
       
    88 	{
       
    89 	RFileLogger f;
       
    90 	if (f.Connect() == KErrNone)
       
    91 		{
       
    92 		f.CreateLog(aTag, aFile, EFileLoggingModeAppend);
       
    93 		TInt i = 0;
       
    94 		while (KOptions[i].iCode != OpCode() && ++i < KNumberOfSupportedOptions){/*do nothing*/}
       
    95 		
       
    96 		TInt n = iPtr8[1];
       
    97 		if (i < KNumberOfSupportedOptions)
       
    98 			{
       
    99 			f.WriteFormat(_L8("Option Code: %s, length: %d"), KOptions[i].iName, n);
       
   100 			}
       
   101 		else
       
   102 			{
       
   103 			f.WriteFormat(_L( "Option Code: %d, length %d" ), OpCode(), n );
       
   104 			}
       
   105 		if (GetItemLength() > 2)
       
   106 			{
       
   107 			f.HexDump(NULL, NULL, GetBodyPtr(), GetLength());
       
   108 			}
       
   109 		f.CloseLog();
       
   110 		f.Close();
       
   111 		}
       
   112 	}
       
   113 #else
       
   114 const SOptionHeader KOptions[KNumberOfSupportedOptions]= 
       
   115 	{   //iCode,           iExpLength, iAlignment, iMinLength 
       
   116 		{EDHCPSubnetMask,       4,       1,          6}, //must be the first option
       
   117 		{EDHCPRouter,           0,       4,          6},
       
   118 #ifdef SYMBIAN_NETWORKING_DHCPSERVER		
       
   119 		{EDHCPNameServer, 		0,       4,          6},
       
   120 #endif 	//  SYMBIAN_NETWORKING_DHCPSERVER	
       
   121 		{EDHCPDomainNameServer, 0,       4,          6},
       
   122 		{EDHCPHostName,         0,       1,          3},
       
   123 		{EDHCPDomainName,       0,       1,          3},
       
   124 		{EDHCPBroadcastAddr,    4,       4,          6},
       
   125 		{EDHCPRequestedIPAddr,  4,       4,          6},
       
   126 		{EDHCPLeaseTime,        4,       4,          6},
       
   127 		{EDHCPMessageType,      1,       1,          3},
       
   128 		{EDHCPServerID,         4,       4,          6},
       
   129 		{EDHCPParameterReqList, 0,       1,          3},
       
   130 		{EDHCPMaxMsgSize,       2,       2,          4},
       
   131 		{EDHCPRenewalT1,        4,       4,          6},
       
   132 		{EDHCPRebindT2,         4,       4,          6},
       
   133 		{EDHCPClientID,         0,       1,          4},
       
   134 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
   135 		{EDHCPTftpServerName,   0,		 1,			 3},
       
   136 		{EDHCPOptionOverload,   0,		 1,			 3},
       
   137 		{EDHCPTftpServers,		0,		1,			3},
       
   138 #endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
   139 		{EDHCPSIPServers,		0,		1,			3}
       
   140 	};
       
   141 #endif
       
   142 
       
   143 void COptionList::ParseL(TPtr8& aDes8)
       
   144 /**
       
   145   * Parse message to set pointers into descriptor buffer
       
   146   * at locations of each option supplied in a response msg
       
   147   *
       
   148   * @internalTechnology
       
   149   */
       
   150 	{
       
   151 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL")));
       
   152 	ASSERT(!iRecord.iFirst);
       
   153 
       
   154 	COptionNode** ppNode = reinterpret_cast<COptionNode**>(&iRecord.iFirst);
       
   155 	TUint8 nCode = *aDes8.Ptr();
       
   156 	COptionNode* pNode;
       
   157 	TInt i, nItemLen, nHeaderLength;
       
   158 	while (nCode != EDHCPEnd && aDes8.Length() > 0)
       
   159 		{
       
   160 		for (i = 0; KOptions[i].iCode != nCode && ++i < KNumberOfSupportedOptions;) {}
       
   161 		nHeaderLength = (nCode == EDHCPPad) ? KEDHCPPadLength : KOptionHeaderLength; 
       
   162 		pNode = new(ELeave) COptionNode(nHeaderLength);
       
   163 		
       
   164 		/* ppNode is a pointer to a pointer. It has not got assigned any dynamically allocated memory. But coverity has misinterpreted it an issue.*/
       
   165 		// coverity [SYMBIAN.CLEANUP STACK]
       
   166 		// coverity [leave_without_push]
       
   167 		CleanupStack::PushL(pNode);
       
   168 		
       
   169 		/* 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 .*/
       
   170 		// coverity[deref_ptr_in_call]	
       
   171 		pNode->ParseL(aDes8);
       
   172 		nItemLen = pNode->GetItemLength();
       
   173 		
       
   174 		if (aDes8.Length() > 0)
       
   175 			{
       
   176 			nCode = *aDes8.Ptr();
       
   177 			}
       
   178 		else
       
   179 			{
       
   180 			__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL Option list ended without EDHCPEnd flag")));
       
   181 			}
       
   182 
       
   183 		if (i < KNumberOfSupportedOptions)
       
   184 			{
       
   185 			// now do some sanity checks and leave if bad results
       
   186 			TInt nPayloadLength = nItemLen - nHeaderLength;
       
   187 			*ppNode = pNode;
       
   188 
       
   189 			if (nItemLen < KOptions[i].iMinLength)	// min length check
       
   190 				{
       
   191 				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL BadDescriptor 2")));
       
   192 				*ppNode = NULL;
       
   193 				User::Leave(KErrBadDescriptor);
       
   194 				}
       
   195 
       
   196 			if (nPayloadLength % KOptions[i].iAlignment != 0)	// alignment check
       
   197 				{
       
   198 				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL BadDescriptor 3")));
       
   199 				*ppNode = NULL;
       
   200 				User::Leave(KErrBadDescriptor);
       
   201 				}
       
   202 
       
   203 			if (KOptions[i].iExpLength > 0 && nPayloadLength != KOptions[i].iExpLength)	//expected length check
       
   204 				{
       
   205 				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL BadDescriptor 4")));
       
   206 				*ppNode = NULL;
       
   207 				User::Leave(KErrBadDescriptor);
       
   208 				}
       
   209 
       
   210 			ppNode = reinterpret_cast<COptionNode**>(&(pNode->iNext));
       
   211 			CleanupStack::Pop(pNode);
       
   212 			}
       
   213 		else
       
   214 			{
       
   215 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
   216 			//make sure we parse everything becz we support every option now
       
   217 			if (pNode)
       
   218 				{
       
   219 				*ppNode = pNode;
       
   220 				ppNode = reinterpret_cast<COptionNode**>(&(pNode->iNext));
       
   221 				CleanupStack::Pop(pNode);
       
   222 				}
       
   223 			else
       
   224 				{
       
   225 #endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
   226  			__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("COptionList::ParseL Code Not Found")));
       
   227 
       
   228 			/* ppNode is a pointer to a pointer. It has not got assigned any dynamically allocated memory. But coverity has misinterpreted it an issue.*/
       
   229 			// coverity [SYMBIAN.CLEANUP STACK]
       
   230 			// coverity [memory_leak]
       
   231  			CleanupStack::PopAndDestroy(pNode);
       
   232  			pNode=NULL;
       
   233 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
   234 				}
       
   235 #endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
   236 			}
       
   237 		}
       
   238 
       
   239 
       
   240 	}
       
   241 
       
   242 COptionNode* COptionList::AddNodeL(TInt aInitialLength, TInt aHeaderLength)
       
   243 /**
       
   244   * Create a new node for an option in the message
       
   245   *
       
   246   * @internalTechnology
       
   247   */
       
   248 	{
       
   249 	COptionNode* pNode = new(ELeave) COptionNode(aHeaderLength);
       
   250 	AddNode(pNode);
       
   251 	pNode->Header().SetInitialValue(aInitialLength);
       
   252 	return pNode;
       
   253 	}
       
   254 
       
   255 COptionNode* COptionList::FindOption(TUint8 aOpCode) const
       
   256 /**
       
   257   * Find the location of an option in the message and return a pointer to it
       
   258   *
       
   259   * @internalTechnology
       
   260   */
       
   261 	{
       
   262 	COptionNode* pNode = static_cast<COptionNode*>(iRecord.iFirst);
       
   263 	while (pNode && pNode->OpCode() != aOpCode)
       
   264 		{
       
   265 		pNode = static_cast<COptionNode*>(pNode->iNext);
       
   266 		}
       
   267 	return pNode;
       
   268 	}
       
   269 
       
   270 TInt COptionList::NumberOfItemsInAddressListOption(TUint8 aOpCode) const
       
   271 /**
       
   272   * Return the number of addresses
       
   273   * from the specified server option.
       
   274   *
       
   275   * @internalTechnology
       
   276   */
       
   277 	{
       
   278 	COptionNode* pNode = FindOption(aOpCode);
       
   279 	return pNode ? pNode->GetLength()/KIp4AddrByteLength : 0;
       
   280 	}
       
   281 
       
   282 TUint32 COptionList::GetAddressFromAddressListOption(TUint8 aOpCode,TInt aPos) const
       
   283 /**
       
   284   * Return the address at position aPos in the specified server option code
       
   285   * in TUint32 format.
       
   286   *
       
   287   * @param aPos Indicates which one of the addresses in the list to return
       
   288   * @return TUint32 The address 
       
   289   *
       
   290   * @internalTechnology
       
   291   */
       
   292 	{
       
   293  	COptionNode* pNode = FindOption(aOpCode);
       
   294 	return pNode ? BigEndian::Get32(pNode->GetBodyPtr() + aPos * KIp4AddrByteLength) : 0;
       
   295 	}
       
   296 
       
   297 
       
   298 TUint32 COptionList::GetValueBigEndian(TUint8 aOpCode) const
       
   299 /**
       
   300   * Return a value from the message in big endian format
       
   301   *
       
   302   * @internalTechnology
       
   303   */
       
   304 	{
       
   305 	COptionNode* pNode = FindOption(aOpCode);
       
   306 	return pNode ? pNode->GetBigEndian() : 0;
       
   307 	}
       
   308 
       
   309 TInt COptionList::NumberOfDomainServers() const
       
   310 /**
       
   311   * Return the number of domain name server addresses
       
   312   * from the domain name server option.  There are
       
   313   * expected to be more than one.
       
   314   *
       
   315   * @internalTechnology
       
   316   */
       
   317 	{
       
   318 	return NumberOfItemsInAddressListOption(EDHCPDomainNameServer);
       
   319 	}
       
   320 
       
   321 TUint32 COptionList::GetDomainNameServer(TInt aPos) const
       
   322 /**
       
   323   * Return the domain name server address at position aPos
       
   324   * in TUint32 format.
       
   325   *
       
   326   * @param aPos Indicates which one of the domain name server addresses to return
       
   327   * @return TUint32 The address of the domain name server
       
   328   *
       
   329   * @internalTechnology
       
   330   */
       
   331 	{
       
   332 	return GetAddressFromAddressListOption(EDHCPDomainNameServer,aPos);
       
   333 	}
       
   334 
       
   335 
       
   336 
       
   337 TBool COptionList::CopyHostNameL(HBufC8*& aBuf8) const
       
   338 /**
       
   339   * Return a copy of the host name given in the message
       
   340   *
       
   341   * @param aBuf8 A descriptor for the host name to be written into
       
   342   * @return TBool If the copy was successful or not 
       
   343   *
       
   344   * @internalTechnology
       
   345   */
       
   346 	{
       
   347 	COptionNode* pNode = FindOption(EDHCPHostName);
       
   348 	if (pNode)
       
   349 		{
       
   350 		pNode->CopyBodyToL(aBuf8);
       
   351 		}
       
   352 	return pNode != NULL;
       
   353 	}
       
   354 
       
   355 TBool COptionList::CopyDomainNameL(HBufC8*& aBuf8) const
       
   356 /**
       
   357   * Return a copy of the domain name given in the message 
       
   358   *
       
   359   * @param aBuf8 A descriptor for the domain name to be written into
       
   360   * @return TBool If the copy was successful or not 
       
   361   */
       
   362 	{
       
   363 	COptionNode* pNode = FindOption(EDHCPDomainName);
       
   364 	if (pNode)
       
   365 		{
       
   366 		pNode->CopyBodyToL(aBuf8);
       
   367 		}
       
   368 	return pNode != NULL;
       
   369 	}
       
   370 
       
   371 CDHCPMessageHeaderIP4::CDHCPMessageHeaderIP4(HBufC8*& aMsg) :
       
   372 	CDHCPMessageHeader(&iXid, 4, aMsg), //|     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
       
   373 		iXid(&iSecs, 4), iSecs(&iFlags, 2), iFlags(&iCiaddr, 2),
       
   374 		iCiaddr(&iYiaddr, 4), iYiaddr(&iSiaddr, 4), iSiaddr(&iGiaddr, 4),
       
   375 		iGiaddr(&iChaddr, 4), iChaddr(&iSname, 16), iSname(&iFile, 64),
       
   376 		iFile(&iCookie, 128), iCookie(&iOptions, 4),
       
   377 		iOptions(NULL)
       
   378 		{
       
   379 #ifdef _FLOG_ACTIVE
       
   380 		iName = _L("op ht hl ho");
       
   381 		iXid.iName = _L("Xid");
       
   382 		iSecs.iName = _L("Secs");
       
   383 		iFlags.iName = _L("Flags");
       
   384 		iCiaddr.iName = _L("Ciaddr");
       
   385 		iYiaddr.iName = _L("Yiaddr");
       
   386 		iSiaddr.iName = _L("Siaddr");
       
   387 		iGiaddr.iName = _L("Giaddr");
       
   388 		iChaddr.iName = _L("Chaddr");
       
   389 		iSname.iName = _L("Sname");
       
   390 		iFile.iName = _L("File");
       
   391 		iCookie.iName = _L("Cookie");
       
   392 #endif
       
   393 		}
       
   394 	
       
   395 CDHCPMessageHeaderIP4::~CDHCPMessageHeaderIP4()
       
   396 	{
       
   397 	Close();
       
   398 	}
       
   399 
       
   400 COptionNode* CDHCPMessageHeaderIP4::AddOptionL(TDHCPOptionCodes aOpCode, TInt aLength)
       
   401 /**
       
   402   * First stage of adding an option to the message. Calls AddNode to create space
       
   403   * for message.
       
   404   *
       
   405   * @param aOpCode The opcode of the options to be added
       
   406   * @param aLength The length of the option data
       
   407   * @return COptionNode* The pointer to the option in the message
       
   408   *
       
   409   @ @internalTechnology
       
   410   */
       
   411 	{
       
   412 	COptionNode* pNode = iOptions.AddNodeL(aLength, aLength > 0 ? KOptionHeaderLength : 1);
       
   413 	TPtr8 ptr = iMsg->Des();
       
   414 	pNode->InitialiseL(ptr);
       
   415 	pNode->SetOpCode(static_cast<TUint8>(aOpCode));
       
   416 	return pNode;
       
   417 	}
       
   418 
       
   419 #ifdef SYMBIAN_NETWORKING_DHCPSERVER
       
   420 void CDHCPMessageHeaderIP4::ParseClientMsgL()
       
   421 	{
       
   422 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPMessageHeaderIP4::ParseL")));
       
   423 	
       
   424 	TPtr8 ptr = iMsg->Des();
       
   425 	iRecord.ParseL(ptr);
       
   426 	// now it is parsed, first check whether this is actually a REPLY message from a DHCP Server...
       
   427 	if (GetOpCode() != EDHCPBootRequest)
       
   428 		{
       
   429 		User::Leave(KErrNotFound);
       
   430 		}
       
   431 	}	
       
   432 
       
   433 void CDHCPMessageHeaderIP4::GetCHAddr(TSockAddr& aSockAddr) 
       
   434 /**
       
   435   * Retrieve Your IP Address from message
       
   436   *
       
   437   * @internalTechnology  *
       
   438   */
       
   439 	{
       
   440 	aSockAddr.SetFamily(KAFUnspec);
       
   441 	aSockAddr.SetLength(KHwAddrOffset);
       
   442 	aSockAddr.Append(iChaddr.GetBodyDes());
       
   443 	}	
       
   444 #ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION
       
   445 void CDHCPMessageHeaderIP4::GetClientHwAddr(TSockAddr& aSockAddr) 
       
   446 	{
       
   447 /**
       
   448   * Return the Client Hardware Address.
       
   449   *
       
   450   * @internalTechnology
       
   451   */
       
   452 	aSockAddr.Append(iChaddr.GetBodyDes());
       
   453 	}
       
   454 #endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION
       
   455 #endif // SYMBIAN_NETWORKING_DHCPSERVER		
       
   456 	
       
   457 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
   458 void CDHCPMessageHeaderIP4::FinishL(TDesC8& aClientId, const TDesC8* aOptionsPtr)
       
   459 /**
       
   460   * Put finishing touches to message for sending. Mainly used for sending DHCPINFORM message 
       
   461   * Puts the requested parameter list to 'Parameter Request List' 
       
   462   * If aFlag is set to TRUE, then all parameters have to requested including default parameters+extra requested parameters
       
   463   * Basically copies in the magic cookie (99.130.83.99)
       
   464   * and the end marker then set the length of the descriptor
       
   465   * as we have been pushing data into the descriptor manually
       
   466   *
       
   467   * @see RFC 2131 for explanation of the magic cookie!
       
   468   * @param aClientId The client ID string to be added to the message
       
   469   * @param aOptionsPtr Contains a list of opcodes to be sent in the parameter list of the DHCPINFORM message
       
   470   *
       
   471   * @internalTechnology
       
   472   */
       
   473 #else 
       
   474 void CDHCPMessageHeaderIP4::FinishL(TDesC8& aClientId)
       
   475 /**
       
   476   * Put finishing touches to message for sending
       
   477   * Basically copies in the magic cookie (99.130.83.99)
       
   478   * and the end marker then set the length of the descriptor
       
   479   * as we have been pushing data into the descriptor manually
       
   480   *
       
   481   * @param aClientId The client ID string to be added to the message
       
   482   * @see RFC 2131 for explanation of the magic cookie!
       
   483   *
       
   484   * @internalTechnology
       
   485   */
       
   486 #endif //SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
   487 	{
       
   488 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPMessageBase::FinishL")));
       
   489 	
       
   490 #ifdef SYMBIAN_NETWORKING_DHCPSERVER
       
   491 	if(!iDHCPServerImpl)
       
   492 	{
       
   493 #endif // SYMBIAN_NETWORKING_DHCPSERVER	
       
   494 	
       
   495 	TUint8 reqListArray[KDhcpParameterRequestListLen] = {EDHCPHostName, EDHCPDomainNameServer, 
       
   496 							EDHCPDomainName, EDHCPSubnetMask, EDHCPRouter, EDHCPBroadcastAddr, EDHCPSIPServers};
       
   497 	TPtr8 ptr(reqListArray, KDhcpParameterRequestListLen, KDhcpParameterRequestListLen);
       
   498 	
       
   499 	// +++++++++++++++++++++++ Client ID +++++++++++++++++++++++++++++++++++++++++/
       
   500 	AddOptionL(EDHCPClientID, aClientId.Length())->GetBodyDes().Copy(aClientId);
       
   501 		
       
   502 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
   503 	RBuf8 appendOpCodeList;
       
   504 	appendOpCodeList.CreateL(ptr);
       
   505 	if (aOptionsPtr)
       
   506 		{
       
   507 		TInt optLen=aOptionsPtr->Length();
       
   508 		appendOpCodeList.ReAllocL(KDhcpParameterRequestListLen+optLen);
       
   509 		appendOpCodeList.Append(aOptionsPtr->Ptr(),optLen);
       
   510 		}
       
   511 	AddOptionL(EDHCPParameterReqList, appendOpCodeList.Length())->GetBodyDes().Copy(appendOpCodeList);
       
   512 	appendOpCodeList.Close();
       
   513 #else
       
   514 	// +++++++++++++++++++++++ Parameter Request List ++++++++++++++++++++++++++++/
       
   515 	AddOptionL(EDHCPParameterReqList, ptr.Length())->GetBodyDes().Copy(ptr);
       
   516 #endif		
       
   517 	// +++++++++++++++++++++++ Maximum message size (2 bytes) ++++++++++++++++++++/
       
   518 	AddOptionL(EDHCPMaxMsgSize, 2)->SetBigEndian(KDhcpMaxMsgSizeIP4);
       
   519 	
       
   520 #ifdef SYMBIAN_NETWORKING_DHCPSERVER
       
   521 	}
       
   522 #endif // SYMBIAN_NETWORKING_DHCPSERVER	
       
   523 		
       
   524 	TInetAddr magic;
       
   525 	_LIT(magicCookie, "99.83.130.99");
       
   526 	User::LeaveIfError(magic.Input(magicCookie));	// essential the magic cookie is correct
       
   527 	iCookie.SetLittleEndian(magic.Address());
       
   528 		
       
   529 	ASSERT(!iOptions.FindOption(EDHCPEnd));
       
   530 	AddOptionL(EDHCPEnd, 0);
       
   531 
       
   532    //add padding if msg shorter than 300 bytes
       
   533  	TInt len=iMsg->Length();
       
   534  	TPtr8 des=iMsg->Des();
       
   535 	if (len<300)
       
   536       {
       
   537 		des.AppendFill(EDHCPPad, 300-len);
       
   538       }
       
   539 	}
       
   540 	
       
   541 void CDHCPMessageHeaderIP4::ParseL()
       
   542 /**
       
   543   * When a response is received to a message
       
   544   * this function will unpack the response by creating
       
   545   * option objects which can be easily used to retrieve 
       
   546   * the values returned in these options.  Providing 
       
   547   * this functionality hides the nasty descriptor operations. 
       
   548   *
       
   549   * Each option class has a pointer set to the start point
       
   550   * of their data in the response message.
       
   551   *
       
   552   * There is no need to explicitly unpack the mandatory fields
       
   553   * of the DHCP message that has been returned.  Accessor functions
       
   554   * simply extract the data sraight out of the decsriptor.
       
   555   *
       
   556   * @internalTechnology
       
   557   */
       
   558 	{
       
   559 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPMessageHeaderIP4::ParseL")));
       
   560 	
       
   561 	TPtr8 ptr = iMsg->Des();
       
   562 	iRecord.ParseL(ptr);
       
   563 	// now it is parsed, first check whether this is actually a REPLY message from a DHCP Server...
       
   564 	if (GetOpCode() != EDHCPBootReply)
       
   565 		{
       
   566 		User::Leave(KErrNotFound);
       
   567 		}
       
   568 	}
       
   569 	
       
   570 	
       
   571 void CDHCPMessageHeaderIP4::SetHeader(TUint8 aOpCode,TUint8 aType,TUint8 aLength,TUint8 aHops)
       
   572 /**
       
   573   * Sets Op Code in message
       
   574   *
       
   575   * @internalTechnology
       
   576   *
       
   577   */
       
   578 	{
       
   579 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPMessageHeaderIP4::SetHeader")));
       
   580 		
       
   581 	TUint8* ptr = &(GetBodyPtr()[0]);
       
   582 	*ptr = aOpCode;
       
   583 	*++ptr = aType;
       
   584 	*++ptr = aLength;
       
   585 	*++ptr = aHops;
       
   586 	}
       
   587 	
       
   588 void CDHCPMessageHeaderIP4::SetCHAddr(TSockAddr& aAddr)
       
   589 /**
       
   590   * Sets If Hardware Address in message
       
   591   *
       
   592   * @internalTechnology
       
   593   * 
       
   594   */
       
   595 	{
       
   596 	TUint len = aAddr.Length()-KHwAddrOffset;
       
   597 	if(len > KIp4ChAddrMaxLength) { len = KIp4ChAddrMaxLength; }
       
   598 	iChaddr.GetBodyDes().Copy(aAddr.Mid(KHwAddrOffset, len));
       
   599 	}
       
   600 
       
   601 void CDnsUpdateOption::ToStringL(RBuf8& aBuf8) const
       
   602 /**
       
   603   * Writes DNS update option data to a string suitable for sending out
       
   604   * on to the network
       
   605   *
       
   606   * @internalTechnology
       
   607   * 
       
   608   */
       
   609 	{
       
   610 	RBuf8 encodedDomainName;
       
   611 	encodedDomainName.CleanupClosePushL();
       
   612 
       
   613 	TDomainNameArray domainNames;
       
   614 	CleanupClosePushL(domainNames);
       
   615 	domainNames.AppendL(iDomainName);
       
   616 
       
   617 	CDomainNameCodec* domainNameEncoder = new(ELeave) CDomainNameCodec();
       
   618 	CleanupStack::PushL(domainNameEncoder);
       
   619 
       
   620 
       
   621 	domainNameEncoder->EncodeL(domainNames, encodedDomainName);
       
   622 
       
   623 
       
   624 	CleanupStack::PopAndDestroy(domainNameEncoder);
       
   625 	CleanupStack::PopAndDestroy(&domainNames); // closes the RBuf8	
       
   626 
       
   627 
       
   628 	aBuf8.Zero();
       
   629 
       
   630 	aBuf8.ReAllocL( 3 + encodedDomainName.Length() );
       
   631 
       
   632 	aBuf8.Append((TChar)(iFlags.Value()));
       
   633 	aBuf8.Append((TChar)iRCode1);
       
   634 	aBuf8.Append((TChar)iRCode2);
       
   635 	aBuf8.Append(encodedDomainName);
       
   636 
       
   637 	CleanupStack::PopAndDestroy(&encodedDomainName); // closes the array
       
   638 	}
       
   639 
       
   640