Beispiel #1
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;
        }
Beispiel #2
0
 public override void Reset()
 {
     base.Reset();
       LastAddressResult = null;
       AddressIterator = null;
       CNameIterator = null;
       //TCRepeating = false;
       RootCacheState = true;
 }
Beispiel #3
0
 protected override void Dispose(bool disposing)
 {
     if (disposing)
     {
         try
         {
             if (AddressIterator != null)
             {
                 ((IDisposable)AddressIterator).Dispose();
             }
             if (CNameIterator != null)
             {
                 ((IDisposable)CNameIterator).Dispose();
             }
         }
         finally
         {
             AddressIterator = null;
             CNameIterator   = null;
         }
     }
     base.Dispose(disposing);
 }
Beispiel #4
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
        }
Beispiel #5
0
 protected override void Dispose(bool disposing)
 {
     if (disposing)
       {
     try
     {
       if (AddressIterator != null)
     ((IDisposable)AddressIterator).Dispose();
       if (CNameIterator != null)
     ((IDisposable)CNameIterator).Dispose();
     }
     finally
     {
       AddressIterator = null;
       CNameIterator = null;
     }
       }
       base.Dispose(disposing);
 }
Beispiel #6
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
        }