diff -r abbed5a4b42a -r 8d540f55e491 tcpiputils/dhcp/src/DHCPIP4StateMachine.cpp --- a/tcpiputils/dhcp/src/DHCPIP4StateMachine.cpp Tue Aug 31 16:45:15 2010 +0300 +++ b/tcpiputils/dhcp/src/DHCPIP4StateMachine.cpp Wed Sep 01 12:33:58 2010 +0100 @@ -82,7 +82,13 @@ CDHCPStateMachine::ConstructL(); __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::ConstructL"))); - + if (iConfig) + { + // Parse dhcp.ini for additional options to be requested with server + // and append the option codes to the parameter request list + TRAP_IGNORE(AppendMultipleExtraOptionsParamL()); + } + ReAllocL(KDhcpMaxMsgSizeIP4); iDhcpMessage = new(ELeave)CDHCPMessageHeaderIP4(iFragment); iMessageSender = new(ELeave)CMessageSender(this,iSocket,&iTaskStartedAt,KAfInet); @@ -476,7 +482,9 @@ else { #endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS - DhcpMessage()->FinishL(iClientId); + // From tb92 and later, including iSavedExtraParameters for FinishL() + // as SYMBIAN_NETWORKING_DHCP_MSG_HEADERS is expected to be always ON + DhcpMessage()->FinishL(iClientId,&iSavedExtraParameters); #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS } #endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS @@ -1506,10 +1514,24 @@ __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4StateMachine::ConfigureInterfaceL - KSoNoSourceAddressSelect"))); User::LeaveIfError(iSocket.SetOpt(KSoNoSourceAddressSelect, KSolInetIp, 0)); - TSoInet6InterfaceInfo interfaceInfo; + // Using the new structure derived from TSoInet6InterfaceInfo + // to be able to set domain search list for the interface + TSoInetInterfaceInfoExtnDnsSuffix interfaceInfo; CDHCPMessageHeaderIP4* v4Msg = DhcpMessage(); + + // Read the optiond data buffer for option 119 and decrypt it + HBufC8* domainSearchBuf(NULL); + v4Msg->iOptions.CopyDomainSearchL(domainSearchBuf); + if (domainSearchBuf) + { + // Perform decryption only if option data has been returned by dhcp server + SplitDomainSearchBufferL(domainSearchBuf); + delete domainSearchBuf; + domainSearchBuf = NULL; + } + if (!IsUsingStaticAddress()) { iCurrentAddress.SetAddress(v4Msg->GetYIAddr()); @@ -1581,8 +1603,24 @@ interfaceInfo.iDoState = ETrue; interfaceInfo.iDoAnycast = EFalse; interfaceInfo.iDoProxy = EFalse; + + // Depending on number of domain suffix(es) received from the DHCP server, + // we have to call CDHCPStateMachine::ConfigureInterfaceL multiple times + TUint suffixCount = iSuffixList.Count(); + + if (suffixCount > 0) + interfaceInfo.iDomainSuffix.Copy(iSuffixList[0]); + // If there is no domain suffix available for updating the interface, + // we end up calling ConfigureInterfaceL once CDHCPStateMachine::ConfigureInterfaceL( interfaceInfo ); + + // Repeat ConfigureInterface call for each domain suffix returned from the server + for (TUint index = 1; index < suffixCount; index++) + { + interfaceInfo.iDomainSuffix.Copy(iSuffixList[index]); + CDHCPStateMachine::ConfigureInterfaceL( interfaceInfo ); + } } void CDHCPIP4StateMachine::CreateFqdnUpdateRequestL() @@ -1875,4 +1913,175 @@ return EFalse; } #endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION + +/** + * @name AppendMultipleExtraOptionsParam + * Parses dhcp.ini for extra dhcp options and adds them to + * the dhcp server's parameter request list + * + * @internalTechnology + */ +void CDHCPIP4StateMachine::AppendMultipleExtraOptionsParamL() + { + TBuf8 iniValue; + User::LeaveIfError(IniRead(KDhcpExtraOptions, iniValue)); + + TLex8 iniLex(iniValue); + TChar ch; + + while((ch = iniLex.Get()) != 0) + { + TUint8 opCode(ch); + TPtr8 opCodePtr(&opCode,1,1); + + if (!iSavedExtraParameters.Length()) + { + iSavedExtraParameters.CreateL(opCodePtr); + } + else + { + iSavedExtraParameters.ReAllocL(iSavedExtraParameters.Length()+opCodePtr.Length()); + iSavedExtraParameters.Append(opCodePtr); + } + } + } + +/** + * @name SplitDomainSearchBufferL + * Decrypt dhcp server option data response for option code 119 + * and retrieve the domain search list for configuring the interface + * + * @internalTechnology + */ +void CDHCPIP4StateMachine::SplitDomainSearchBufferL(HBufC8* aDomainSearchBuf) + { + typedef TBuf8 THostName8; + const TInt KMaxDomainSearchBufferLength = 4096; + + // Retrieve the total length of the option data content + TPtr8 ptr(aDomainSearchBuf->Des()); + TInt totalLength = 0; + totalLength = aDomainSearchBuf->Length(); + + // Create a buffer of a length capable + // to hold domain search list from the option data + TLex8 primaryLex; + RBuf8 suffixList; + suffixList.CreateL(KMaxDomainSearchBufferLength); + + // To overcome specific limitations of TLex + // Converting all '0's to '@'s in the option data buffer + TInt offset = 0; + THostName8 tmpBuf; + while((offset = ptr.Locate(0)) != KErrNotFound) + { + tmpBuf.Append(ptr.MidTPtr(0, offset)); + tmpBuf.Append('@'); + if (ptr.Length() > (offset +1)) + ptr.Set(ptr.MidTPtr((offset+1))); + else + ptr.SetLength(0); + } + ptr.Set(tmpBuf.MidTPtr(0)); + primaryLex.Assign(ptr.Ptr()); + + + // Creating temporary objects for parsing the buffer + THostName8 domainName; + domainName.SetLength(0); + TInt noOfDomainNames = 0; + TChar ch; + + /* Start of decryption algorithm implementation for the option data buffer + * Synopsis + * Option data contains domain suffixes seaparated by either a '@' or a two-octet compression pointer i.e. C004 (hex) + * which points to offset 4 in the complete aggregated block of Domain Search Option data + * where another validly encoded domain name can be found to complete the name + * Each sub-domain in a domain name is defined by a digit representing number of characters following this digit + */ + for (TInt i=0; i domainName16; + domainName16.Copy(domainName); + iSuffixList.AppendL(domainName16); + domainName.FillZ(); + domainName.SetLength(0); + primaryLex.Inc(); + noOfDomainNames++; + } + else if (ch < 48) // if the character is a digit + { + // Marks '.' completing a sub-domain and defines the length + // of the next sub-domain in the option data buffer + if (domainName.Length() != 0) + { + suffixList.Append('.'); + domainName.Append('.'); + } + TInt domainPartLength(ch); + suffixList.Append(ptr.Mid(i+1,ch)); + domainName.Append(ptr.Mid(i+1,ch)); + + TInt inc = (TInt)ch + 1; + i+=(TInt)ch; + primaryLex.Inc(inc); + } + else if (ch == 192) // if the character is a hex 0xC0 + { + // Marks start of compression pointer + // Looks up to the suffixList buffer created earlier that holds + // the domain names read until now in contigous sequence + // for extracting the remainder of the sub-domains to complete the domain name + if (domainName.Length() != 0) + { + suffixList.Append('.'); + domainName.Append('.'); + } + i++; + primaryLex.Inc(); + ch = primaryLex.Peek(); + TInt refOffset(ch), actOffset=0; + THostName compressedDomain; + TPtr8 tmpPtr(suffixList.MidTPtr(0)); + TLex8 tmpLex(tmpPtr); + TInt ind=0; + for (; ind < tmpPtr.Length() && actOffset < refOffset; ind++) + { + TChar ch1 = tmpLex.Peek(); + if (ch1 != 46 && ch1 != 64) + actOffset++; + tmpLex.Inc(); + } + tmpPtr.Set(tmpPtr.MidTPtr(ind-1)); + tmpPtr.Set(tmpPtr.MidTPtr(0,tmpPtr.Locate('@'))); + suffixList.Append(tmpPtr); + domainName.Append(tmpPtr); + suffixList.Append('@'); + TBuf domainName16; + domainName16.Copy(domainName); + iSuffixList.AppendL(domainName16); + domainName.FillZ(); + domainName.SetLength(0); + primaryLex.Inc(); + noOfDomainNames++; + } + else + { + // Marks completion of the option data buffer + // Free up memory allocated on the heap + suffixList.Close(); + return; + } + } + // End of decryption algorithm implementation for the option data buffer + } + #endif // SYMBIAN_NETWORKING_DHCPSERVER