tcpiputils/dnd/src/dns.cpp
branchRCL_3
changeset 53 7e41d162e158
parent 0 af10295192d8
child 57 abbed5a4b42a
equal deleted inserted replaced
52:3652a10b304a 53:7e41d162e158
   283 	{
   283 	{
   284 	TInetAddr tmp;
   284 	TInetAddr tmp;
   285 	TBool ret = FALSE;
   285 	TBool ret = FALSE;
   286 
   286 
   287 	if (iCurrentServer == 0)
   287 	if (iCurrentServer == 0)
       
   288 	    {
   288 		ret = iOwner->iServerManager.OpenList(iFilter, this) > 0;
   289 		ret = iOwner->iServerManager.OpenList(iFilter, this) > 0;
       
   290 		// if suffix support is enabled in the resolver.ini
       
   291 		// and query request had been initiated from a implicitly connected host resolver
       
   292 		// Perform checks to find appropriate interface that can support the domain name
       
   293 		// and update the server filter for the network id it should forward its request to
       
   294 		if (iSuffixSupportEnabled && iFlowReqType == 0)
       
   295 			iOwner->iServerManager.UpdateDomain(iFilter);
       
   296 #ifdef _LOG
       
   297 		if (iNetworkId != iFilter.iLockId)
       
   298 			Log::Printf(_L("\t\tDNS session [%u] domain suffix match resulted in change of net id from %d to %d"), (TInt)this, iNetworkId, iFilter.iLockId);
       
   299 #endif
       
   300 	    }
   289 	iOwner->iCache->GetServerAddress(iOwner->iServerManager.NameSpace(iFilter, iCurrentServer), tmp);
   301 	iOwner->iCache->GetServerAddress(iOwner->iServerManager.NameSpace(iFilter, iCurrentServer), tmp);
   290 	iFilter.iServerId = iOwner->iServerManager.ServerId(tmp);
   302 	iFilter.iServerId = iOwner->iServerManager.ServerId(tmp);
   291 	iCurrentServer = iOwner->iServerManager.Next(iFilter, 0);
   303 	iCurrentServer = iOwner->iServerManager.Next(iFilter, 0);
   292 #ifdef _LOG
   304 #ifdef _LOG
   293 	if (iCurrentServer)
   305 	if (iCurrentServer)
   408 		iOwner->DeactivateSocket();
   420 		iOwner->DeactivateSocket();
   409 	}
   421 	}
   410 
   422 
   411 // TDndReqData::NewQuery
   423 // TDndReqData::NewQuery
   412 // ***********************
   424 // ***********************
   413 TInt TDndReqData::NewQuery(const TDnsMessage &aQuery, TDnsServerScope aServerScope, TUint32 aFlags)
   425 TInt TDndReqData::NewQuery(const TDnsMessage &aQuery, TDnsServerScope aServerScope, TUint32 aFlags, TBool aSuffixSupportEnabled)
   414 	{
   426 	{
   415 	iIsReqPending = FALSE;
   427 	iIsReqPending = FALSE;
   416 	iIsNewQuery = TRUE;
   428 	iIsNewQuery = TRUE;
   417 	iIsUsingTCP = 0;
   429 	iIsUsingTCP = 0;
   418 	iQdCount = 1;
   430 	iQdCount = 1;
   419 	iFlags = aFlags;
   431 	iFlags = aFlags;
   420 	iFilter.iServerScope = aServerScope;
   432 	iFilter.iServerScope = aServerScope;
   421 	iFilter.iServerId = 0;
   433 	iFilter.iServerId = 0;
   422 	iNetworkId = aQuery.iId;  // Get the networkId information from the Query.
   434 	iNetworkId = aQuery.iId;  			// Get the networkId information from the Query.
       
   435 	iFlowReqType = aQuery.iFlowRequestType; // Get the IMPLICIT/EXPLICIT differentiation from the Query
       
   436 	iSuffixSupportEnabled = aSuffixSupportEnabled; // Whether suffix support enabled in the resolver.ini
       
   437 	iIsIncompleteHostName = FALSE;		// Whether the query name is not fully qualified name
       
   438 	iCanResolveIncompleteName = TRUE;	// Flag to confirm incomplete name without domain suffix tried for resolution as it is
       
   439 	iPendingSuffixExist = FALSE;		// Identifies whether all of the available suffixes has been tried out
       
   440 	iFilter.iDomainName.FillZ();
       
   441 	iFilter.iDomainName.SetLength(0);
   423 
   442 
   424 #ifdef SYMBIAN_DNS_PUNYCODE
   443 #ifdef SYMBIAN_DNS_PUNYCODE
   425 	if( (aQuery.iScope & 0x80) == 0x80 )
   444 	if( (aQuery.iScope & 0x80) == 0x80 )
   426 		{
   445 		{
   427 		iIdnEnabled = 1;
   446 		iIdnEnabled = 1;
   441 			{
   460 			{
   442 			const TNameRecord &query = aQuery.NameRecord();
   461 			const TNameRecord &query = aQuery.NameRecord();
   443 
   462 
   444 			if (aQuery.iType == KDnsRequestType_GetByName)
   463 			if (aQuery.iType == KDnsRequestType_GetByName)
   445 				{
   464 				{
       
   465 				THostName queryName(query.iName);
       
   466 	
       
   467 				// if the query is a qualified name, pick the domain name from the query
       
   468 				// and update the server filter for the performing interface selection
       
   469 				TInt posOfDomainNameStart = queryName.Locate('.');
       
   470 			    if (posOfDomainNameStart != KErrNotFound)
       
   471 			        {
       
   472 			        iFilter.iDomainName = queryName.Mid(posOfDomainNameStart+1);
       
   473 			        }
       
   474 			        
   446 				iFilter.iLockId = aQuery.iId;
   475 				iFilter.iLockId = aQuery.iId;
   447 				iFilter.iLockType = KIp6AddrScopeNetwork;
   476 				iFilter.iLockType = KIp6AddrScopeNetwork;
   448 #ifdef SYMBIAN_DNS_PUNYCODE
   477 #ifdef SYMBIAN_DNS_PUNYCODE
   449 				TInt err = iQuestion.SetName(query.iName);
   478 				TInt err = iQuestion.SetName(queryName);
   450 				if( err != KErrNone)
   479 				if( err != KErrNone)
   451 					{
   480 					{
   452 					return err;
   481 					return err;
   453 					}
   482 					}
       
   483 				iActualQueryName.Copy(queryName);
   454 #else
   484 #else
   455 				iQuestion.SetName(query.iName);
   485 				iQuestion.SetName(queryName);
       
   486 				iActualQueryName.Copy(queryName);
   456 #endif // SYMBIAN_DNS_PUNYCODE
   487 #endif // SYMBIAN_DNS_PUNYCODE
   457 				}
   488 				}
   458 			else
   489 			else
   459 				{
   490 				{
   460 				iOwner->iServerManager.LockByAddress(TInetAddr::Cast(query.iAddr), aQuery.iId, iFilter);
   491 				iOwner->iServerManager.LockByAddress(TInetAddr::Cast(query.iAddr), aQuery.iId, iFilter);
   654 	// -- should only look from cache if aQType is not a "wildcard" type
   685 	// -- should only look from cache if aQType is not a "wildcard" type
   655 	//    (however, if wildcard, cache should not give hits...)
   686 	//    (however, if wildcard, cache should not give hits...)
   656 	iQuestion.SetQType(aQType);
   687 	iQuestion.SetQType(aQType);
   657 	// -- only IN class queries are supported
   688 	// -- only IN class queries are supported
   658 	iQuestion.SetQClass(EDnsQClass_IN);
   689 	iQuestion.SetQClass(EDnsQClass_IN);
       
   690 	// Possible that the there is a different interface (other than the default)
       
   691 	// that can resolve the domain name we are interested at.
       
   692 	// By this time, we would have updated the netid in the filter, if at all
       
   693 	iNetworkId = iFilter.iLockId;
   659 
   694 
   660 	if (iRecord)
   695 	if (iRecord)
   661 		{
   696 		{
   662 		iRecord->Unlock(this);
   697 		iRecord->Unlock(this);
   663 		iRecord = NULL;
   698 		iRecord = NULL;
   685 	if (id == 0)
   720 	if (id == 0)
   686 		{
   721 		{
   687 		SendResponse(KErrDndServerUnusable);
   722 		SendResponse(KErrDndServerUnusable);
   688 		return 0;
   723 		return 0;
   689 		}
   724 		}
   690 				
   725 
       
   726 
       
   727 	// Check to see if the query is not fully qualified
       
   728     THostName queryName;
       
   729     iQuestion.GetName(queryName);
       
   730     if (queryName.Locate('.') == KErrNotFound)
       
   731         {
       
   732 		// If query is not fully qualified, set flags to mark this for further processing
       
   733         iIsIncompleteHostName = TRUE;
       
   734 		// Pick the domain suffix list on the interface
       
   735 	    iOwner->iServerManager.InterfaceSuffixList(iCurrentServer, iSuffixList);
       
   736 		// If count of suffices is 0, mark this, so that we do not have to perform any special processing
       
   737         if (iSuffixList.Count() > 0)
       
   738             iPendingSuffixExist = TRUE;
       
   739         }
       
   740 
   691 	// Check in the cache first. If the record does not exist
   741 	// Check in the cache first. If the record does not exist
   692 	// in the cache, it will be created now (empty with KErrNotFound).
   742 	// in the cache, it will be created now (empty with KErrNotFound).
   693 	iRecord = iOwner->iCache->FindL(
   743 	iRecord = iOwner->iCache->FindL(
   694 			id,
   744 			id,
   695 			iQuestion,
   745 			iQuestion,
   932 		case EDnsRcode_NOERROR:
   982 		case EDnsRcode_NOERROR:
   933 			break;
   983 			break;
   934 		case EDnsRcode_FORMAT_ERROR:
   984 		case EDnsRcode_FORMAT_ERROR:
   935 			return KErrDndFormat;
   985 			return KErrDndFormat;
   936 		case EDnsRcode_SERVER_FAILURE:
   986 		case EDnsRcode_SERVER_FAILURE:
   937 			return KErrDndServerFailure;
   987 			/*
       
   988 			In case the server returns the server failure, we just ignore the error code and treat it as server unusable. so that the query is sent to the other available servers for resolution. Need more reasonable solution ???-- 
       
   989 			return KErrDndServerFailure;  */
       
   990 			return KErrDndServerUnusable;
   938 		case EDnsRcode_NAME_ERROR:
   991 		case EDnsRcode_NAME_ERROR:
   939 			return KErrDndBadName;
   992 			return KErrDndBadName;
   940 		case EDnsRcode_NOT_IMPLEMENTED:
   993 		case EDnsRcode_NOT_IMPLEMENTED:
   941 			return KErrDndNotImplemented;
   994 			return KErrDndNotImplemented;
   942 		case EDnsRcode_REFUSED:
   995 		case EDnsRcode_REFUSED:
  1062 
  1115 
  1063 	if (dns.iServerManager.Address(iCurrentServer, aServer) != KErrNone)
  1116 	if (dns.iServerManager.Address(iCurrentServer, aServer) != KErrNone)
  1064 		return 0;
  1117 		return 0;
  1065 	ASSERT(aServer.Port() != 0);
  1118 	ASSERT(aServer.Port() != 0);
  1066 
  1119 
       
  1120 	// If the query us incomplete and we have pending domain suffix that can be applied
       
  1121 	// lets try to update the query name and forward it to the next level
       
  1122     if ( iIsIncompleteHostName )
       
  1123         {
       
  1124 		if ( iPendingSuffixExist )
       
  1125 			{
       
  1126 	        THostName queryName;
       
  1127 	        iQuestion.GetName(queryName);
       
  1128 	        
       
  1129 	        if ( queryName.Locate('.') == KErrNotFound )
       
  1130 	            {
       
  1131 				// If the query does not have a '.', we understand that the query has not tried 
       
  1132 				// any of the suffixes. So, lets apply the first domain suffix from the interface
       
  1133 	            TInt newLength = queryName.Length() + iSuffixList[0].Length();
       
  1134 	            THostName qName(queryName);
       
  1135 	            qName.Append(_L("."));
       
  1136 	            
       
  1137 	            // If the query name + suffix name exceeds allowed limit for length (256)
       
  1138 	            // truncate the suffix name while appending to the min possible length
       
  1139 	            // this automagically skips from getting resolved as the buffer does not have 
       
  1140 	            // enough space to append configuration msg along with it
       
  1141 	            if (newLength < KMaxHostNameLength)
       
  1142 	                qName.Append(iSuffixList[0]);
       
  1143 	            else
       
  1144 	                qName.Append(iSuffixList[0].Mid(0, KMaxHostNameLength - qName.Length()));
       
  1145 	            
       
  1146 	            iQuestion.SetName(qName);
       
  1147 	            
       
  1148 	            if ( iSuffixList.Count() == 1 )
       
  1149 	                iPendingSuffixExist = FALSE;
       
  1150 	                
       
  1151 	            LOG(Log::Printf(_L("\t\t Query name after appending suffix = %S"), &qName));
       
  1152 	            }
       
  1153 	        else
       
  1154 	            {
       
  1155 				// As we dont have a '.', we understand that there is some domain suffix already tried
       
  1156 				// and we have reached here because, we were not able to resolve with that domain suffix
       
  1157 				// Now, lets figure out in sequence, as to which one was applied previously
       
  1158 				// so that we shall apply the next one in the list and forward it for resolution
       
  1159 	            for (TInt index=0; /*iPendingSuffixExist*/ ; index++ )
       
  1160 	                {
       
  1161 	                // Crop the leadng query name and '.' from the previous query and check to see
       
  1162 	                // which suffix in the list was earlier applied
       
  1163 
       
  1164 	                TSuffixName queryNameSuffix( queryName.Mid( iActualQueryName.Length()+1 ) );
       
  1165 	                TSuffixName domainSuffix(iSuffixList[index]);
       
  1166 	                TInt suffixLength = domainSuffix.Length();
       
  1167 	                TInt completeLength = suffixLength + iActualQueryName.Length() + 1;
       
  1168 	                
       
  1169 	                if (completeLength > KMaxHostNameLength)
       
  1170 	                	suffixLength = KMaxHostNameLength - (iActualQueryName.Length() + 1);
       
  1171 	                	
       
  1172 	                if ( queryNameSuffix.Compare( domainSuffix.Mid( 0, suffixLength ) ) != KErrNone )
       
  1173 	                    continue;
       
  1174 	                
       
  1175                     index++;
       
  1176                     TInt newLength = iActualQueryName.Length() + iSuffixList[index].Length();
       
  1177                     THostName qName(iActualQueryName);
       
  1178                     qName.Append(_L("."));
       
  1179                     
       
  1180                     if (newLength < KMaxHostNameLength)
       
  1181                         qName.Append(iSuffixList[index]);
       
  1182                     else
       
  1183                         qName.Append(iSuffixList[index].Mid(0, KMaxHostNameLength - qName.Length()));
       
  1184                     
       
  1185                     iQuestion.SetName(qName);
       
  1186                     
       
  1187                     if ( iSuffixList.Count() == index+1 )
       
  1188                         iPendingSuffixExist = FALSE;
       
  1189 
       
  1190                     LOG(Log::Printf(_L("\t\t Query name after appending suffix = %S"), &qName));
       
  1191                     break;
       
  1192 	                }
       
  1193 	            }
       
  1194 	        }
       
  1195 	    else /* if ( iCanResolveIncompleteName )*/
       
  1196 	        {
       
  1197 	        iQuestion.SetName(iActualQueryName);
       
  1198 	        LOG(Log::Printf(_L("\t\t Query name after appending suffix = %S"), &iActualQueryName));
       
  1199 	        iCanResolveIncompleteName = FALSE;
       
  1200 	        }
       
  1201 		}
       
  1202 
       
  1203     
  1067 	aMsg.SetLength(sizeof(TDndHeader));
  1204 	aMsg.SetLength(sizeof(TDndHeader));
  1068 	TDndHeader &hdr = (TDndHeader &)aMsg.Header();
  1205 	TDndHeader &hdr = (TDndHeader &)aMsg.Header();
  1069 	if (aServer.IsMulticast())
  1206 	if (aServer.IsMulticast())
  1070 		{
  1207 		{
  1071 		ASSERT(iFilter.IsMulticast());
  1208 		ASSERT(iFilter.IsMulticast());
  1173 				}
  1310 				}
  1174 			}
  1311 			}
  1175 		// If cannot use the TCP, then just use the trunctated
  1312 		// If cannot use the TCP, then just use the trunctated
  1176 		// answer as is...
  1313 		// answer as is...
  1177 		}
  1314 		}
       
  1315 		
       
  1316 	// If a incomplete query has failed to resolve after application of a domain suffix
       
  1317 	// and we know that we still have some pending suffix that can be applied
       
  1318 	// let us retry with the available suffices
       
  1319 	LOG(Log::Printf(_L("Error from name resolution is %d"),err));
       
  1320     if( err == KErrDndBadName && iIsIncompleteHostName && (iPendingSuffixExist || iCanResolveIncompleteName))
       
  1321         {
       
  1322         iOwner->ReSend(*this, ETrue); // Set the retryWithSuffix flag to TRUE so that a new request ID is assigned
       
  1323         return 1;
       
  1324         }
       
  1325 
  1178 	//
  1326 	//
  1179 	// UpdateCacheData updates data in cache only, if err is KErrNone, or
  1327 	// UpdateCacheData updates data in cache only, if err is KErrNone, or
  1180 	// updates error status for some specific err codes,
  1328 	// updates error status for some specific err codes,
  1181 	// otherwise, it does nothing.
  1329 	// otherwise, it does nothing.
  1182 	TBool updated = UpdateCacheData(aBuf, offset, err);
  1330 	TBool updated = UpdateCacheData(aBuf, offset, err);