tcpiputils/dnd/src/dns.cpp
branchRCL_3
changeset 21 abbed5a4b42a
parent 20 7e41d162e158
child 22 8d540f55e491
equal deleted inserted replaced
20:7e41d162e158 21:abbed5a4b42a
   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 	    {
       
   289 		ret = iOwner->iServerManager.OpenList(iFilter, this) > 0;
   288 		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 	    }
       
   301 	iOwner->iCache->GetServerAddress(iOwner->iServerManager.NameSpace(iFilter, iCurrentServer), tmp);
   289 	iOwner->iCache->GetServerAddress(iOwner->iServerManager.NameSpace(iFilter, iCurrentServer), tmp);
   302 	iFilter.iServerId = iOwner->iServerManager.ServerId(tmp);
   290 	iFilter.iServerId = iOwner->iServerManager.ServerId(tmp);
   303 	iCurrentServer = iOwner->iServerManager.Next(iFilter, 0);
   291 	iCurrentServer = iOwner->iServerManager.Next(iFilter, 0);
   304 #ifdef _LOG
   292 #ifdef _LOG
   305 	if (iCurrentServer)
   293 	if (iCurrentServer)
   420 		iOwner->DeactivateSocket();
   408 		iOwner->DeactivateSocket();
   421 	}
   409 	}
   422 
   410 
   423 // TDndReqData::NewQuery
   411 // TDndReqData::NewQuery
   424 // ***********************
   412 // ***********************
   425 TInt TDndReqData::NewQuery(const TDnsMessage &aQuery, TDnsServerScope aServerScope, TUint32 aFlags, TBool aSuffixSupportEnabled)
   413 TInt TDndReqData::NewQuery(const TDnsMessage &aQuery, TDnsServerScope aServerScope, TUint32 aFlags)
   426 	{
   414 	{
   427 	iIsReqPending = FALSE;
   415 	iIsReqPending = FALSE;
   428 	iIsNewQuery = TRUE;
   416 	iIsNewQuery = TRUE;
   429 	iIsUsingTCP = 0;
   417 	iIsUsingTCP = 0;
   430 	iQdCount = 1;
   418 	iQdCount = 1;
   431 	iFlags = aFlags;
   419 	iFlags = aFlags;
   432 	iFilter.iServerScope = aServerScope;
   420 	iFilter.iServerScope = aServerScope;
   433 	iFilter.iServerId = 0;
   421 	iFilter.iServerId = 0;
   434 	iNetworkId = aQuery.iId;  			// Get the networkId information from the Query.
   422 	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);
       
   442 
   423 
   443 #ifdef SYMBIAN_DNS_PUNYCODE
   424 #ifdef SYMBIAN_DNS_PUNYCODE
   444 	if( (aQuery.iScope & 0x80) == 0x80 )
   425 	if( (aQuery.iScope & 0x80) == 0x80 )
   445 		{
   426 		{
   446 		iIdnEnabled = 1;
   427 		iIdnEnabled = 1;
   460 			{
   441 			{
   461 			const TNameRecord &query = aQuery.NameRecord();
   442 			const TNameRecord &query = aQuery.NameRecord();
   462 
   443 
   463 			if (aQuery.iType == KDnsRequestType_GetByName)
   444 			if (aQuery.iType == KDnsRequestType_GetByName)
   464 				{
   445 				{
   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 			        
       
   475 				iFilter.iLockId = aQuery.iId;
   446 				iFilter.iLockId = aQuery.iId;
   476 				iFilter.iLockType = KIp6AddrScopeNetwork;
   447 				iFilter.iLockType = KIp6AddrScopeNetwork;
   477 #ifdef SYMBIAN_DNS_PUNYCODE
   448 #ifdef SYMBIAN_DNS_PUNYCODE
   478 				TInt err = iQuestion.SetName(queryName);
   449 				TInt err = iQuestion.SetName(query.iName);
   479 				if( err != KErrNone)
   450 				if( err != KErrNone)
   480 					{
   451 					{
   481 					return err;
   452 					return err;
   482 					}
   453 					}
   483 				iActualQueryName.Copy(queryName);
       
   484 #else
   454 #else
   485 				iQuestion.SetName(queryName);
   455 				iQuestion.SetName(query.iName);
   486 				iActualQueryName.Copy(queryName);
       
   487 #endif // SYMBIAN_DNS_PUNYCODE
   456 #endif // SYMBIAN_DNS_PUNYCODE
   488 				}
   457 				}
   489 			else
   458 			else
   490 				{
   459 				{
   491 				iOwner->iServerManager.LockByAddress(TInetAddr::Cast(query.iAddr), aQuery.iId, iFilter);
   460 				iOwner->iServerManager.LockByAddress(TInetAddr::Cast(query.iAddr), aQuery.iId, iFilter);
   685 	// -- should only look from cache if aQType is not a "wildcard" type
   654 	// -- should only look from cache if aQType is not a "wildcard" type
   686 	//    (however, if wildcard, cache should not give hits...)
   655 	//    (however, if wildcard, cache should not give hits...)
   687 	iQuestion.SetQType(aQType);
   656 	iQuestion.SetQType(aQType);
   688 	// -- only IN class queries are supported
   657 	// -- only IN class queries are supported
   689 	iQuestion.SetQClass(EDnsQClass_IN);
   658 	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;
       
   694 
   659 
   695 	if (iRecord)
   660 	if (iRecord)
   696 		{
   661 		{
   697 		iRecord->Unlock(this);
   662 		iRecord->Unlock(this);
   698 		iRecord = NULL;
   663 		iRecord = NULL;
   720 	if (id == 0)
   685 	if (id == 0)
   721 		{
   686 		{
   722 		SendResponse(KErrDndServerUnusable);
   687 		SendResponse(KErrDndServerUnusable);
   723 		return 0;
   688 		return 0;
   724 		}
   689 		}
   725 
   690 				
   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 
       
   741 	// Check in the cache first. If the record does not exist
   691 	// Check in the cache first. If the record does not exist
   742 	// in the cache, it will be created now (empty with KErrNotFound).
   692 	// in the cache, it will be created now (empty with KErrNotFound).
   743 	iRecord = iOwner->iCache->FindL(
   693 	iRecord = iOwner->iCache->FindL(
   744 			id,
   694 			id,
   745 			iQuestion,
   695 			iQuestion,
   982 		case EDnsRcode_NOERROR:
   932 		case EDnsRcode_NOERROR:
   983 			break;
   933 			break;
   984 		case EDnsRcode_FORMAT_ERROR:
   934 		case EDnsRcode_FORMAT_ERROR:
   985 			return KErrDndFormat;
   935 			return KErrDndFormat;
   986 		case EDnsRcode_SERVER_FAILURE:
   936 		case EDnsRcode_SERVER_FAILURE:
   987 			/*
   937 			return KErrDndServerFailure;
   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;
       
   991 		case EDnsRcode_NAME_ERROR:
   938 		case EDnsRcode_NAME_ERROR:
   992 			return KErrDndBadName;
   939 			return KErrDndBadName;
   993 		case EDnsRcode_NOT_IMPLEMENTED:
   940 		case EDnsRcode_NOT_IMPLEMENTED:
   994 			return KErrDndNotImplemented;
   941 			return KErrDndNotImplemented;
   995 		case EDnsRcode_REFUSED:
   942 		case EDnsRcode_REFUSED:
  1115 
  1062 
  1116 	if (dns.iServerManager.Address(iCurrentServer, aServer) != KErrNone)
  1063 	if (dns.iServerManager.Address(iCurrentServer, aServer) != KErrNone)
  1117 		return 0;
  1064 		return 0;
  1118 	ASSERT(aServer.Port() != 0);
  1065 	ASSERT(aServer.Port() != 0);
  1119 
  1066 
  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     
       
  1204 	aMsg.SetLength(sizeof(TDndHeader));
  1067 	aMsg.SetLength(sizeof(TDndHeader));
  1205 	TDndHeader &hdr = (TDndHeader &)aMsg.Header();
  1068 	TDndHeader &hdr = (TDndHeader &)aMsg.Header();
  1206 	if (aServer.IsMulticast())
  1069 	if (aServer.IsMulticast())
  1207 		{
  1070 		{
  1208 		ASSERT(iFilter.IsMulticast());
  1071 		ASSERT(iFilter.IsMulticast());
  1310 				}
  1173 				}
  1311 			}
  1174 			}
  1312 		// If cannot use the TCP, then just use the trunctated
  1175 		// If cannot use the TCP, then just use the trunctated
  1313 		// answer as is...
  1176 		// answer as is...
  1314 		}
  1177 		}
  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 
       
  1326 	//
  1178 	//
  1327 	// UpdateCacheData updates data in cache only, if err is KErrNone, or
  1179 	// UpdateCacheData updates data in cache only, if err is KErrNone, or
  1328 	// updates error status for some specific err codes,
  1180 	// updates error status for some specific err codes,
  1329 	// otherwise, it does nothing.
  1181 	// otherwise, it does nothing.
  1330 	TBool updated = UpdateCacheData(aBuf, offset, err);
  1182 	TBool updated = UpdateCacheData(aBuf, offset, err);