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); |