Esempio n. 1
0
        //protected virtual void OnResolutionCompleted(DnsClient.DNS.QTYPE question, DnsClient.Response response)
        //{
        //  IEnumerable<DnsClient.DNS.RR> requested = response.AnswerRecords.OfQuestion(question);
        //  if (requested.Any())
        //  {
        //    // The requested record type was found.
        //    LogMessageCreate(Logging.LogMessageText.RESPONSE.ResolutionSucceded(Resolver.Domain, Question, requested));
        //  }

        //  else
        //  {
        //    // The requested record type was NOT found.
        //    if (question == DnsClient.DNS.QTYPE.ANY)
        //    {
        //      // The question is ANY, so the result is acceptable.
        //      LogMessageCreate(Logging.LogMessageText.RESPONSE.AnyResolutionSucceded(response.AnswerRecords));
        //    }

        //    else
        //    {
        //      // maybe CNAME
        //    }
        //  }
        //}

        #endregion

        #region private

        private Results.ResolutionResult Request(NameServerCollection authorities, out bool isCompleted)
        {
            // perform name server request
            DnsClient.Request request;
            IPAddress         address = authorities.Selected.GetFirstAddress(Resolver.Options.IPVersion);

            DnsClient.Response       response = Resolver.LookUp(address, Question, out request);
            Results.ResolutionResult result   = new Results.ResolutionResult(this.NestingLevel, request, response, authorities);

            // "Request took {0}ms."
            LogMessageCreate(Logging.LogMessageText.RESPONSE.INFO.RequestDuration(result.Duration.TotalMilliseconds));

            if (response.Header.AA)
            {
                // authoritative response
                isCompleted = true;
            }
            else
            {
                // [RFC 1035]
                // Name Error - Meaningful only for responses from an authoritative name server,
                // this code signifies that the  domain name referenced in the query does not exist.

                // stop if the response was any other than NoError or NameError
                isCompleted = !(
                    response.Header.RCODE == DnsClient.DNS.RCODE.NoError ||
                    response.Header.RCODE == DnsClient.DNS.RCODE.NameError);
            }


            return(result);
        }
Esempio n. 2
0
        //// private sub-iterator
        //private ResolutionIterator(ResolutionIterator iterator, DnsDomain domain, DnsClient.DNS.QTYPE question)
        //  : base(new Resolver(iterator.Resolver, domain), question, iterator.AddressCache)
        //{
        //  IsSubIterator = true;
        //}

        #endregion

        #region override

        public override void Reset()
        {
            base.Reset();
            LastAddressResult = null;
            AddressIterator   = null;
            CNameIterator     = null;
            //TCRepeating = false;
            RootCacheState = true;
        }
Esempio n. 3
0
 public override void Reset()
 {
     base.Reset();
       LastAddressResult = null;
       AddressIterator = null;
       CNameIterator = null;
       //TCRepeating = false;
       RootCacheState = true;
 }
Esempio n. 4
0
        private NameServerCollection GetResultAuthorities(Results.ResolutionResult result)
        {
            // get authority records from existing result


            NameServerCollection authorities = NameServerCollection.Create(
                result.Response.AuthorityRecords, result.Response.AdditionalRecords);

            // save top level name server cache
            if (!RootCacheState)
            {
                RootServers.Cache.Set(authorities.ZoneName, authorities);
                RootCacheState = true;
            }

            return(authorities);
        }
Esempio n. 5
0
        public IEnumerable <DnsClient.DNS.Records.Address> GetAddresses(Results.ResolutionResult result)
        {
            IEnumerable <DnsClient.DNS.RR> rrset = null;

            switch (result.QueryState)
            {
            case QueryState.AuthoritativeAnswer:
                rrset = result.Response.AnswerRecords;
                break;

            case QueryState.NonAuthoritativeAnswer:
                rrset = result.Response.AdditionalRecords;
                break;
            }
            if (!object.ReferenceEquals(null, rrset))
            {
                return(rrset.Select <DnsClient.DNS.Records.Address>().Where(
                           a => this.Resolver.Domain.Equals(a.Base.NAME)));
            }

            return(null);
        }
Esempio n. 6
0
        protected override Results.ResolutionResult GetNextResult(out bool isCompleted, NameServer selected)
        {
            Results.ResolutionResult result = base.GetNextResult(out isCompleted, selected);
            if (isCompleted)
            {
                IEnumerable <DnsClient.DNS.RR> rrset = null;
                switch (result.QueryState)
                {
                case QueryState.AuthoritativeAnswer:
                    rrset = result.Response.AnswerRecords;
                    break;

                case QueryState.NonAuthoritativeAnswer:
                    rrset = result.Response.AdditionalRecords;
                    break;
                }
                if (!object.ReferenceEquals(null, rrset))
                {
                    this.Addresses = rrset.Select <DnsClient.DNS.Records.Address>().Where(
                        a => this.Resolver.Domain.Equals(a.Base.NAME));
                }
            }
            return(result);
        }
Esempio n. 7
0
        protected override Results.ResolutionResult GetNextResult(out bool isCompleted, NameServer selected)
        {
            // Iteration may be delegated to CNameIterator if the requested name
            // has been identified as alias.
            if (!object.ReferenceEquals(null, CNameIterator))
            {
                CNameIterator.EnsureConnection(Resolver.Client);
                return(CNameIterator.GetNextResult(out isCompleted, selected));
            }

            // A subsequent iteration may be running if a name server address needs to be resolved.
            if (!object.ReferenceEquals(null, AddressIterator))
            {
                AddressIterator.EnsureConnection(Resolver.Client);

                bool isAddressIteratorCompleted;
                Results.ResolutionResult addressResult = AddressIterator.GetNextResult(out isAddressIteratorCompleted, selected);
                if (isAddressIteratorCompleted)
                {
                    // remember the last result from the subsequent iteration
                    ResolvedAddresses = AddressIterator.GetAddresses(addressResult).ToArray();
                    if (!ResolvedAddresses.Any())
                    {
                        // Failed to resolve
                        isCompleted = true;
                    }

                    LastAddressResult = addressResult;

                    AddressIterator.Dispose();
                    AddressIterator = null;
                }
                isCompleted = false;
                return(addressResult);
            }

            // Apply address result from previous step.
            if (!object.ReferenceEquals(null, LastAddressResult))
            {
                // An address iteration has been completed in the previous step.
                try
                {
                    // Apply the resulting address records to the selected authority.
                    IEnumerable <DnsClient.DNS.Records.Address> addresses;
                    if (LastAddressResult.Response.Header.AA)
                    {
                        // fetch addresses from authoritative respone
                        addresses = LastAddressResult.Response.AnswerRecords.OfType <
                            DnsClient.DNS.Records.Address>().Where(a => StoredAuthorities.Selected.Name.Equals(a.Base.NAME));
                    }
                    else
                    {
                        // fetch address from additional records
                        addresses = LastAddressResult.Response.AdditionalRecords.OfType <
                            DnsClient.DNS.Records.Address>().Where(a => StoredAuthorities.Selected.Name.Equals(a.Base.NAME));
                    }
                    if (addresses.Any())
                    {
                        StoredAuthorities.Selected.ApplyAddresses(addresses);
                        OnNameServerResolved(StoredAuthorities.Selected);
                    }
                }
                finally
                {
                    LastAddressResult = null;
                }
            }

            else
            {
                // The standard case
                // Ensure StoredAuthorities with a resolved selected name server.

                if (object.ReferenceEquals(null, StoredAuthorities)) // initial state
                {
                    StoredAuthorities = GetStartAuthorities();
                    OnResolutionStart(StoredAuthorities);
                }
                else
                {
                    OnResolutionContinue(StoredAuthorities);
                }

                // apply cached address records to the set of authorities
                StoredAuthorities.ApplyCache(AddressCache);

                // Select randomly any name server unless one was explicitly chosen.
                if (!object.ReferenceEquals(null, selected))
                {
                    StoredAuthorities.SelectOne(selected);
                }
                else
                {
                    selected = StoredAuthorities.SelectAny();
                }
                OnAuthoritySelected(StoredAuthorities);

                if (!selected.IsResolved)
                {
                    // start a subsequent iteration to resolve the selected name server
                    OnNameServerResolution(selected);
                    AddressIterator = CreateAddressIterator(selected.Name);

                    return(GetNextResult(out isCompleted, null));
                }
            }


            // Perform the actual name server request.
            Results.ResolutionResult result = Request(StoredAuthorities, out isCompleted);

            try // Internal.QueryException
            {
                Internal.QueryProcessor query = new Internal.QueryProcessor(Resolver.Domain, Question, result.Response);
                Internal.QueryResult    qr    = query.Process();
                result.QueryState = qr.State;
                switch (qr.State)
                {
                case QueryState.NextAuthorities:
                    //StoredAuthorities = GetResultAuthorities(result);
                    isCompleted = false;
                    OnNextAuthorities(StoredAuthorities.Selected, qr.NextAuthorities);

                    StoredAuthorities      = qr.NextAuthorities;
                    result.NextAuthorities = StoredAuthorities;


                    // "Received {1} '{0}' authorities from '{2}'."
                    //LogMessageCreate(Logging.LogMessageText.RESPONSE.INFO.NextAuthoritiesReceived(  StoredAuthorities.Selected, result.NextAuthorities));
                    break;

                case QueryState.FollowCName:
                    // CNAME found.
                    isCompleted = true;
                    OnCNameFound(qr.CanonicalName);

                    // Follow, if it's configured.
                    if (Resolver.Options.FollowCanonical)
                    {
                        // Start a new iteration with the canonical name and the same question.
                        // Name servers may or may not be given.
                        CNameIterator = CreateCNameIterator(qr.CanonicalName, qr.NextAuthorities);
                        isCompleted   = false;
                    }
                    break;

                case QueryState.NonAuthoritativeAnswer:
                    isCompleted = true;
                    OnResolutionSucceeded(result.Response, qr.Answers);
                    break;

                case QueryState.AuthoritativeAnswer:
                    // At least one record of the requested type was found.
                    isCompleted = true;
                    OnResolutionSucceeded(result.Response, qr.Answers);
                    break;

                case QueryState.NxDomain:
                    isCompleted = true;
                    LogMessageCreate(Logging.LogMessageText.RESPONSE.ERROR.NameNotExisting(qr.CanonicalName ?? Resolver.Domain));
                    break;

                case QueryState.NoData:
                case QueryState.EmptyResponse:
                    isCompleted = true;
                    LogMessageCreate(Logging.LogMessageText.RESPONSE.ERROR.NegativeResponse(qr.State));
                    break;

                case QueryState.UnexpectedRCode:
                    isCompleted = true;
                    OnRCodeNonZero(result.Response);
                    break;
                }
            }
            catch (Internal.QueryException ex)
            {
                isCompleted       = true;
                result.QueryState = ex.State;
                LogMessageCreate(Logging.LogMessageText.RESPONSE.ERROR.ResponseInvalid(ex.State));
            }


            return(result);



            // =====================================================================

            #region hidden
            //// Dealing with non-Zero RCODE.
            //if (isCompleted && result.Response.Header.RCODE != DnsClient.DNS.RCODE.NoError)
            //{
            //  OnRCodeNonZero(result.Response);
            //  return result;
            //}

            //// cache response address records
            //AddressCache.Set(result.Response.AnswerRecords.OfType<DnsClient.DNS.Records.Address>());
            //if (!Resolver.Options.StrictAuhtoritative) // optionally cache also additional address records
            //{
            //  AddressCache.Set(result.Response.AdditionalRecords.Select<DnsClient.DNS.Records.Address>());
            //}

            //if (result.Response.Header.TC)
            //{
            //  // If the result was truncated, the request can be repeated once.
            //  if (Resolver.Options.RepeatTruncated && !TCRepeating)
            //  {
            //    TCRepeating = true;
            //    isCompleted = false;
            //    OnRepeatTruncated();
            //    return result;
            //  }
            //}
            //TCRepeating = false;

            //if (isCompleted)
            //{
            //  // There was an authoritative response.

            //  DnsClient.DNS.Records.SOA soa = result.Response.AnswerRecords.OfType<DnsClient.DNS.Records.SOA>().FirstOrDefault();


            //  // answer records matching the question
            //  IEnumerable<DnsClient.DNS.RR> requested = result.Response.AnswerRecords;
            //  if (Question != DnsClient.DNS.QTYPE.ANY)
            //  {
            //    // A particular record type has been queried (not ANY).
            //    requested = requested.OfQuestion(Question);
            //  }

            //  if (requested.Any())
            //  {
            //    // At least one record of the requested type was found.
            //    OnResolutionSucceeded(result.Response, requested);
            //  }


            //  // check for CNAME
            //  //
            //  // [RFC 1034], 5.2.2. Aliases
            //  //
            //  // In most cases a resolver simply restarts the query at the new name when
            //  // it encounters a CNAME.  However, when performing the general function,
            //  // the resolver should not pursue aliases when the CNAME RR matches the
            //  // query type.  This allows queries which ask whether an alias is present.
            //  // For example, if the query type is CNAME, the user is interested in the
            //  // CNAME RR itself, and not the RRs at the name it points to.
            //  DnsClient.DNS.Records.CNAME cname;
            //  if (!object.ReferenceEquals(null, (
            //    cname = result.Response.AnswerRecords.FirstOrDefault<DnsClient.DNS.Records.CNAME>())))
            //  {
            //    // CNAME found.
            //    //OnCNameFound(cname);

            //    if (Question != DnsClient.DNS.QTYPE.CNAME)
            //    {
            //      // A CNAME can lead to the zone itself.
            //      if (!object.ReferenceEquals(null, soa) &&
            //        DnsDomain.Equals(soa.Base.NAME, cname.CANONICAL))
            //      {

            //        // TODO


            //      }


            //    }



            //    // Follow, if it's configured and the question was not CNAME.
            //    if (!Question.Equals(DnsClient.DNS.QTYPE.CNAME) &&
            //      Resolver.Options.FollowCanonical)
            //    {
            //      // Start a new iteration with the canonical name and the same question.
            //      CNameIterator = CreateCNameIterator((DnsDomain)cname.CANONICAL);
            //      isCompleted = false;
            //    }
            //  }

            //  else
            //  {
            //    // no matching CNAME found
            //    if (!requested.Any())
            //    {
            //      // Neither an appropriate CNAME nor the requested RR type was found.
            //      OnMissingRecords(result.Response);
            //    }
            //  }



            //  if (NestingLevel == 0)
            //  {
            //    // "Resolution finished."
            //    LogMessageCreate(Logging.LogMessageText.RESPONSE.INFO.ResolutionFinished(IterationCount));
            //  }


            //}

            //else
            //{
            //  // The iteration is not yet completed: get authorities for the next step.
            //  StoredAuthorities = GetResultAuthorities(result);
            //  result.NextAuthorities = StoredAuthorities;
            //  if (StoredAuthorities.IsEmpty)
            //    throw new ResolverException(
            //      "No authority name servers were found although the respone is non-authoritative.");

            //  // "Received {1} '{0}' authorities from '{2}'."
            //  LogMessageCreate(Logging.LogMessageText.RESPONSE.INFO.NextAuthoritiesReceived(result.Authorities.Selected, result.NextAuthorities));
            //}

            //return result;
            #endregion
        }
Esempio n. 8
0
        private Results.ResolutionResult Request(NameServerCollection authorities, out bool isCompleted)
        {
            // perform name server request
              DnsClient.Request request;
              IPAddress address = authorities.Selected.GetFirstAddress(Resolver.Options.IPVersion);

              DnsClient.Response response = Resolver.LookUp(address, Question, out request);
              Results.ResolutionResult result = new Results.ResolutionResult(this.NestingLevel, request, response, authorities);

              // "Request took {0}ms."
              LogMessageCreate(Logging.LogMessageText.RESPONSE.INFO.RequestDuration(result.Duration.TotalMilliseconds));

              if (response.Header.AA)
              {
            // authoritative response
            isCompleted = true;
              }
              else
              {
            // [RFC 1035]
            // Name Error - Meaningful only for responses from an authoritative name server,
            // this code signifies that the  domain name referenced in the query does not exist.

            // stop if the response was any other than NoError or NameError
            isCompleted = !(
              response.Header.RCODE == DnsClient.DNS.RCODE.NoError ||
              response.Header.RCODE == DnsClient.DNS.RCODE.NameError);
              }

              return result;
        }
Esempio n. 9
0
        protected override Results.ResolutionResult GetNextResult(out bool isCompleted, NameServer selected)
        {
            // Iteration may be delegated to CNameIterator if the requested name
              // has been identified as alias.
              if (!object.ReferenceEquals(null, CNameIterator))
              {
            CNameIterator.EnsureConnection(Resolver.Client);
            return CNameIterator.GetNextResult(out isCompleted, selected);
              }

              // A subsequent iteration may be running if a name server address needs to be resolved.
              if (!object.ReferenceEquals(null, AddressIterator))
              {
            AddressIterator.EnsureConnection(Resolver.Client);

            bool isAddressIteratorCompleted;
            Results.ResolutionResult addressResult = AddressIterator.GetNextResult(out isAddressIteratorCompleted, selected);
            if (isAddressIteratorCompleted)
            {
              // remember the last result from the subsequent iteration
              ResolvedAddresses = AddressIterator.GetAddresses(addressResult).ToArray();
              if (!ResolvedAddresses.Any())
              {
            // Failed to resolve
            isCompleted = true;
              }

              LastAddressResult = addressResult;

              AddressIterator.Dispose();
              AddressIterator = null;
            }
            isCompleted = false;
            return addressResult;
              }

              // Apply address result from previous step.
              if (!object.ReferenceEquals(null, LastAddressResult))
              {
            // An address iteration has been completed in the previous step.
            try
            {
              // Apply the resulting address records to the selected authority.
              IEnumerable<DnsClient.DNS.Records.Address> addresses;
              if (LastAddressResult.Response.Header.AA)
              {
            // fetch addresses from authoritative respone
            addresses = LastAddressResult.Response.AnswerRecords.OfType<
              DnsClient.DNS.Records.Address>().Where(a => StoredAuthorities.Selected.Name.Equals(a.Base.NAME));
              }
              else
              {
            // fetch address from additional records
            addresses = LastAddressResult.Response.AdditionalRecords.OfType<
              DnsClient.DNS.Records.Address>().Where(a => StoredAuthorities.Selected.Name.Equals(a.Base.NAME));
              }
              if (addresses.Any())
              {
            StoredAuthorities.Selected.ApplyAddresses(addresses);
            OnNameServerResolved(StoredAuthorities.Selected);
              }
            }
            finally
            {
              LastAddressResult = null;
            }
              }

              else
              {
            // The standard case
            // Ensure StoredAuthorities with a resolved selected name server.

            if (object.ReferenceEquals(null, StoredAuthorities)) // initial state
            {
              StoredAuthorities = GetStartAuthorities();
              OnResolutionStart(StoredAuthorities);
            }
            else
            {
              OnResolutionContinue(StoredAuthorities);
            }

            // apply cached address records to the set of authorities
            StoredAuthorities.ApplyCache(AddressCache);

            // Select randomly any name server unless one was explicitly chosen.
            if (!object.ReferenceEquals(null, selected))
            {
              StoredAuthorities.SelectOne(selected);
            }
            else
            {
              selected = StoredAuthorities.SelectAny();
            }
            OnAuthoritySelected(StoredAuthorities);

            if (!selected.IsResolved)
            {
              // start a subsequent iteration to resolve the selected name server
              OnNameServerResolution(selected);
              AddressIterator = CreateAddressIterator(selected.Name);

              return GetNextResult(out isCompleted, null);
            }
              }

              // Perform the actual name server request.
              Results.ResolutionResult result = Request(StoredAuthorities, out isCompleted);

              try // Internal.QueryException
              {
            Internal.QueryProcessor query = new Internal.QueryProcessor(Resolver.Domain, Question, result.Response);
            Internal.QueryResult qr = query.Process();
            result.QueryState = qr.State;
            switch (qr.State)
            {

              case QueryState.NextAuthorities:
            //StoredAuthorities = GetResultAuthorities(result);
            isCompleted = false;
            OnNextAuthorities(StoredAuthorities.Selected, qr.NextAuthorities);

            StoredAuthorities = qr.NextAuthorities;
            result.NextAuthorities = StoredAuthorities;

            // "Received {1} '{0}' authorities from '{2}'."
            //LogMessageCreate(Logging.LogMessageText.RESPONSE.INFO.NextAuthoritiesReceived(  StoredAuthorities.Selected, result.NextAuthorities));
            break;

              case QueryState.FollowCName:
            // CNAME found.
            isCompleted = true;
            OnCNameFound(qr.CanonicalName);

            // Follow, if it's configured.
            if (Resolver.Options.FollowCanonical)
            {
              // Start a new iteration with the canonical name and the same question.
              // Name servers may or may not be given.
              CNameIterator = CreateCNameIterator(qr.CanonicalName, qr.NextAuthorities);
              isCompleted = false;
            }
            break;

              case QueryState.NonAuthoritativeAnswer:
            isCompleted = true;
            OnResolutionSucceeded(result.Response, qr.Answers);
            break;

              case QueryState.AuthoritativeAnswer:
            // At least one record of the requested type was found.
            isCompleted = true;
            OnResolutionSucceeded(result.Response, qr.Answers);
            break;

              case QueryState.NxDomain:
            isCompleted = true;
            LogMessageCreate(Logging.LogMessageText.RESPONSE.ERROR.NameNotExisting(qr.CanonicalName ?? Resolver.Domain));
            break;

              case QueryState.NoData:
              case QueryState.EmptyResponse:
            isCompleted = true;
            LogMessageCreate(Logging.LogMessageText.RESPONSE.ERROR.NegativeResponse(qr.State));
            break;

              case QueryState.UnexpectedRCode:
            isCompleted = true;
            OnRCodeNonZero(result.Response);
            break;

            }
              }
              catch (Internal.QueryException ex)
              {
            isCompleted = true;
            result.QueryState = ex.State;
            LogMessageCreate(Logging.LogMessageText.RESPONSE.ERROR.ResponseInvalid(ex.State));
              }

              return result;

              // =====================================================================

              #region hidden
              //// Dealing with non-Zero RCODE.
              //if (isCompleted && result.Response.Header.RCODE != DnsClient.DNS.RCODE.NoError)
              //{
              //  OnRCodeNonZero(result.Response);
              //  return result;
              //}

              //// cache response address records
              //AddressCache.Set(result.Response.AnswerRecords.OfType<DnsClient.DNS.Records.Address>());
              //if (!Resolver.Options.StrictAuhtoritative) // optionally cache also additional address records
              //{
              //  AddressCache.Set(result.Response.AdditionalRecords.Select<DnsClient.DNS.Records.Address>());
              //}

              //if (result.Response.Header.TC)
              //{
              //  // If the result was truncated, the request can be repeated once.
              //  if (Resolver.Options.RepeatTruncated && !TCRepeating)
              //  {
              //    TCRepeating = true;
              //    isCompleted = false;
              //    OnRepeatTruncated();
              //    return result;
              //  }
              //}
              //TCRepeating = false;

              //if (isCompleted)
              //{
              //  // There was an authoritative response.

              //  DnsClient.DNS.Records.SOA soa = result.Response.AnswerRecords.OfType<DnsClient.DNS.Records.SOA>().FirstOrDefault();

              //  // answer records matching the question
              //  IEnumerable<DnsClient.DNS.RR> requested = result.Response.AnswerRecords;
              //  if (Question != DnsClient.DNS.QTYPE.ANY)
              //  {
              //    // A particular record type has been queried (not ANY).
              //    requested = requested.OfQuestion(Question);
              //  }

              //  if (requested.Any())
              //  {
              //    // At least one record of the requested type was found.
              //    OnResolutionSucceeded(result.Response, requested);
              //  }

              //  // check for CNAME
              //  //
              //  // [RFC 1034], 5.2.2. Aliases
              //  //
              //  // In most cases a resolver simply restarts the query at the new name when
              //  // it encounters a CNAME.  However, when performing the general function,
              //  // the resolver should not pursue aliases when the CNAME RR matches the
              //  // query type.  This allows queries which ask whether an alias is present.
              //  // For example, if the query type is CNAME, the user is interested in the
              //  // CNAME RR itself, and not the RRs at the name it points to.
              //  DnsClient.DNS.Records.CNAME cname;
              //  if (!object.ReferenceEquals(null, (
              //    cname = result.Response.AnswerRecords.FirstOrDefault<DnsClient.DNS.Records.CNAME>())))
              //  {
              //    // CNAME found.
              //    //OnCNameFound(cname);

              //    if (Question != DnsClient.DNS.QTYPE.CNAME)
              //    {
              //      // A CNAME can lead to the zone itself.
              //      if (!object.ReferenceEquals(null, soa) &&
              //        DnsDomain.Equals(soa.Base.NAME, cname.CANONICAL))
              //      {

              //        // TODO

              //      }

              //    }

              //    // Follow, if it's configured and the question was not CNAME.
              //    if (!Question.Equals(DnsClient.DNS.QTYPE.CNAME) &&
              //      Resolver.Options.FollowCanonical)
              //    {
              //      // Start a new iteration with the canonical name and the same question.
              //      CNameIterator = CreateCNameIterator((DnsDomain)cname.CANONICAL);
              //      isCompleted = false;
              //    }
              //  }

              //  else
              //  {
              //    // no matching CNAME found
              //    if (!requested.Any())
              //    {
              //      // Neither an appropriate CNAME nor the requested RR type was found.
              //      OnMissingRecords(result.Response);
              //    }
              //  }

              //  if (NestingLevel == 0)
              //  {
              //    // "Resolution finished."
              //    LogMessageCreate(Logging.LogMessageText.RESPONSE.INFO.ResolutionFinished(IterationCount));
              //  }

              //}

              //else
              //{
              //  // The iteration is not yet completed: get authorities for the next step.
              //  StoredAuthorities = GetResultAuthorities(result);
              //  result.NextAuthorities = StoredAuthorities;
              //  if (StoredAuthorities.IsEmpty)
              //    throw new ResolverException(
              //      "No authority name servers were found although the respone is non-authoritative.");

              //  // "Received {1} '{0}' authorities from '{2}'."
              //  LogMessageCreate(Logging.LogMessageText.RESPONSE.INFO.NextAuthoritiesReceived(result.Authorities.Selected, result.NextAuthorities));
              //}

              //return result;
              #endregion
        }