Example #1
0
        /// <summary>
        /// Find the best matching leaf for a domain.
        /// </summary>
        /// <param name="domain">The domain, considered as a search path.</param>
        /// <param name="now">Reference date determining cache expiration.</param>
        /// <returns></returns>
        public TElement Get(DnsDomain domain, DateTime now)
        {
            if (object.ReferenceEquals(null, domain))
            {
                throw new ArgumentNullException("domain");
            }

            // Best match search:
            // If one searches for "www.example.com", the search will result in the
            // leaf of "example.com" if there is one, but none for "www.example.com".

            // iterate throgh domain labels starting from top level
            using (IEnumerator <DnsLabel> en = domain.GetEnumerator())
            {
                TreeNode nodes = _Nodes;
                while (en.MoveNext())
                {
                    TreeNode subNodes;
                    if (nodes.TryGetValue(en.Current, out subNodes))
                    {
                        nodes = subNodes;
                        continue;
                    }

                    // return this leaf if it exists and is not expired
                    return(nodes.TryGetElement(now));
                }
            }
            return(null);
        }
Example #2
0
        private bool FindCanonical(ref DnsDomain sname)
        {
            bool mapped = false;

            // Resolve CNAME chains within the zone itself
            DnsClient.DNS.Records.CNAME cname;
            List <DnsDomain>            loopctrl = new List <DnsDomain>();

            while (FindCanonical(sname, out cname))
            {
                // name is an alias.
                if (sname.Equals(cname.CANONICAL))
                {
                    // SERVER_ERROR
                    // CName pointing to itself.
                    throw new QueryException(QueryState.CNameSelf, sname);
                }
                if (loopctrl.Contains(sname))
                {
                    // SERVER_ERROR
                    // Loop detected in local CNAME chain.
                    throw new QueryException(QueryState.LocalCNameLoop, sname);
                }

                DnsDomain canonical = (DnsDomain)cname.CANONICAL;
                LogMessageCreate(Logging.LogMessageText.RESPONSE.WARN.CNameFound(sname, canonical));
                sname = canonical;
                loopctrl.Add((DnsDomain)cname.CANONICAL);
                mapped = true;
            }
            return(mapped);
        }
Example #3
0
        public void Set(DnsDomain name, IExpirableElement <TElement> element)
        {
            if (object.ReferenceEquals(null, name))
            {
                throw new ArgumentNullException("name");
            }
            if (object.ReferenceEquals(null, element))
            {
                throw new ArgumentNullException("element");
            }

            // iterate through domain labels starting from top level
            using (IEnumerator <DnsLabel> en = name.GetEnumerator())
            {
                TreeNode nodes = _Nodes;
                while (en.MoveNext())
                {
                    TreeNode subNodes;
                    if (!nodes.TryGetValue(en.Current, out subNodes))
                    {
                        //subNodes = new TreeNode();
                        nodes.Add(en.Current, (subNodes = new TreeNode()));
                        nodes = subNodes;
                    }
                }

                // now here goes the leaf
                nodes.Leaf = element;
            }
        }
Example #4
0
            public static LogMessage ResolutionSucceded(
                DnsDomain domain, DnsClient.DNS.QTYPE question, IEnumerable <DnsClient.DNS.RR> requestedAnswerRecords)
            {
                // must be true:
                // requestedAnswerRecords.Any()

                int count = requestedAnswerRecords.Count();

                if (count == 1)
                {
                    DnsClient.DNS.RR rr = requestedAnswerRecords.First();
                    DnsClient.DNS.Records.Address address;
                    DnsClient.DNS.Records.PTR     pointer;

                    if (!Object.ReferenceEquals(null, (address = rr as DnsClient.DNS.Records.Address)))
                    {
                        // "The name '{0}' was successfully resolved to {1}."
                        return(RESPONSE.INFO.SingleAddressResolutionSucceeded(domain, address.ADDRESS));
                    }

                    if (!Object.ReferenceEquals(null, (pointer = rr as DnsClient.DNS.Records.PTR)))
                    {
                        // "Pointer resolution succeeded with the name '{0}'."
                        return(RESPONSE.INFO.SinglePointerResolutionSucceeded(pointer.PTRDNAME));
                    }

                    // "A Resouce Records of type {0} was found."
                    return(RESPONSE.INFO.RecordResolutionSucceeded(question));
                }

                // "{1} Resouce Records of type {0} were found."
                return(RESPONSE.INFO.RecordResolutionSucceeded(question, count));
            }
Example #5
0
        public NetworkHost(string name)
        {
            if (name == null)
            throw new ArgumentNullException("name", "Value cannot be null.");

              _Name = DnsDomain.Parse(name);
              _Addresses = new List<IPAddress>();
        }
 public DnsResourceRecord(DnsDomain domain, byte[] data, DnsRecordType type, DnsRecordClass klass = DnsRecordClass.IN, TimeSpan ttl = default)
 {
     Name       = domain;
     Type       = type;
     Class      = klass;
     TimeToLive = ttl;
     Data       = data;
 }
Example #7
0
        public NetworkHost(DnsDomain name, IEnumerable<IPAddress> addresses)
        {
            if (name == null)
            throw new ArgumentNullException("name", "Value cannot be null.");
              if (addresses == null)
            throw new ArgumentNullException("addresses", "Value cannot be null.");

              _Name = name;
              _Addresses = new List<IPAddress>(addresses);
        }
Example #8
0
        /// <summary>
        /// Initialize a new instance of the Resolver class.
        /// </summary>
        /// <param name="options">Resolution options</param>
        /// <param name="domain">The domain in question</param>
        public DomainResolver(Options options, DnsDomain domain)
        {
            if (object.ReferenceEquals(null, options))
            throw new ArgumentNullException("options");
              if (object.ReferenceEquals(null, domain))
            throw new ArgumentNullException("domain");

              _Options = options;
              _Domain = domain;
        }
Example #9
0
        //private DnsClient.DNS.QTYPE GetAddressQuestion()
        //{
        //  switch (Resolver.Options.IPVersion)
        //  {
        //    case IPVersion.IPv4:
        //      return DnsClient.DNS.QTYPE.A;
        //    case IPVersion.IPv6:
        //      return DnsClient.DNS.QTYPE.AAAA;
        //    default:
        //      return DnsClient.DNS.QTYPE.ANY;
        //  }
        //}

        //private ResolutionIterator CreateSubIterator(DnsDomain domain, DnsClient.DNS.QTYPE question)
        //{
        //  ResolutionIterator iterator = new ResolutionIterator(this, domain, question);
        //  if (LogMessageCreated != null)
        //  {
        //    iterator.LogMessageCreated += new DnsClient.Logging.LogMessageEventHandler(OnSubIteratorLogMessage);
        //  }
        //  return iterator;
        //}

        private AddressIterator CreateAddressIterator(DnsDomain domain)
        {
            AddressIterator iterator = new Iterators.AddressIterator(this, domain, Resolver.Options.IPVersion);

            if (LogMessageCreated != null)
            {
                iterator.LogMessageCreated += new DnsClient.Logging.LogMessageEventHandler(OnSubIteratorLogMessage);
            }
            return(iterator);
        }
Example #10
0
            public static LogMessage ResolutionStart(DnsDomain name, NameServerCollection authorities)
            {
                if (authorities.ZoneName.Equals(DnsDomain.Root))
                {
                  // "Starting resolution of '{0}' with a root name server."
                  return REQUEST.INFO.StartingResultion(name);
                }

                // "Starting resolution of '{0}' with a '{1}' authority name server."
                return REQUEST.INFO.StartingResultion(name, authorities);
            }
Example #11
0
            public static LogMessage ResolutionStart(DnsDomain name, NameServerCollection authorities)
            {
                if (authorities.ZoneName.Equals(DnsDomain.Root))
                {
                    // "Starting resolution of '{0}' with a root name server."
                    return(REQUEST.INFO.StartingResultion(name));
                }

                // "Starting resolution of '{0}' with a '{1}' authority name server."
                return(REQUEST.INFO.StartingResultion(name, authorities));
            }
Example #12
0
        public DnsClientResponse Resolve(DnsDomain domain, DnsRecordType type)
        {
            var request  = Create();
            var question = new DnsQuestion(domain, type);

            request.Questions.Add(question);
            request.OperationCode    = DnsOperationCode.Query;
            request.RecursionDesired = true;

            return(request.Resolve());
        }
Example #13
0
        protected virtual void OnCNameFound(DnsDomain cname)
        {
            // "The name '{0}' is an alias for the canonical name '{1}'."
            LogMessageCreate(Logging.LogMessageText.RESPONSE.WARN.CNameFound(Resolver.Domain, cname));

            if (!Resolver.Options.FollowCanonical)
            {
                // "The resolver is not configured to follow the canonical name."
                LogMessageCreate(Logging.LogMessageText.RESPONSE.WARN.CNameNoFollow());
            }
        }
Example #14
0
        private Iterators.CNameIterator CreateCNameIterator(DnsDomain cname, NameServerCollection authorities)
        {
            // TODO
            // apply authorties

            Iterators.CNameIterator iterator = new CNameIterator(this, (DnsDomain)cname);
            if (LogMessageCreated != null)
            {
                iterator.LogMessageCreated += new DnsClient.Logging.LogMessageEventHandler(OnSubIteratorLogMessage);
            }
            return(iterator);
        }
Example #15
0
        public string Reverse(IPAddress ip)
        {
            var response = Resolve(DnsDomain.PointerName(ip), DnsRecordType.PTR);
            var ptr      = response.AnswerRecords.FirstOrDefault(r => r.Type == DnsRecordType.PTR);

            if (ptr == null)
            {
                throw new DnsQueryException(response, "No matching records");
            }

            return(((DnsPointerResourceRecord)ptr).PointerDomainName.ToString());
        }
Example #16
0
            public static DnsResourceRecord FromArray(byte[] message, int offset, out int endOffset)
            {
                var domain = DnsDomain.FromArray(message, offset, out offset);
                var tail   = message.ToStruct <Tail>(offset, Tail.SIZE);

                var data = new byte[tail.DataLength];

                offset += Tail.SIZE;
                Array.Copy(message, offset, data, 0, data.Length);

                endOffset = offset + data.Length;

                return(new DnsResourceRecord(domain, data, tail.Type, tail.Class, tail.TimeToLive));
            }
Example #17
0
        public TElement Get(DnsDomain domain, DateTime now)
        {
            IExpirableElement <TElement> result;

            if (Data.TryGetValue(domain, out result))
            {
                if (result.IsExpired(now))
                {
                    Data.Remove(domain);
                    return(null);
                }
                return(result.Element);
            }
            return(null);
        }
Example #18
0
        public async Task <string> Reverse(IPAddress ip)
        {
            if (ip == null)
            {
                throw new ArgumentNullException(nameof(ip));
            }

            var response = await Resolve(DnsDomain.PointerName(ip), DnsRecordType.PTR).ConfigureAwait(false);

            var ptr = response.AnswerRecords.FirstOrDefault(r => r.Type == DnsRecordType.PTR);

            return(ptr == null
                ? throw new DnsQueryException(response, "No matching records")
                : ((DnsPointerResourceRecord)ptr).PointerDomainName.ToString());
        }
Example #19
0
        public bool MoveNext(NameServer selected = null)
        {
            // Verify the selected name server occurs within the NextAuthorities in the previous result.
            if (!object.ReferenceEquals(null, selected))
            {
                DnsDomain selectedName = selected.Name;
                try
                {
                    // Throws if either NullReferenceException or InvalidOperationException on failure.
                    selected = CurrentResult.NextAuthorities.First(n => n.Name.Equals(selectedName));
                }
                catch (Exception ex)
                {
                    throw new ArgumentException(String.Format(
                                                    "The selected name server was not taken from the NextAuthorities in the precious result: {0}",
                                                    selectedName.ToString()), "selected", ex);
                }
            }

            if (IsCompleted)
            {
                return(false);
            }

            // Apply loop control.
            if (_Resolver.Options.IterationLoopControl > 0)
            {
                if (_IterationCount >= Resolver.Options.IterationLoopControl)
                {
                    throw new ResolverException("Maximum number of iterations has been reached.");
                }
            }

            // next
            try
            {
                CurrentResult = GetNextResult(out IsCompleted, selected);
            }
            finally
            {
                _IterationCount++;
            }
            return(true);
        }
Example #20
0
        private bool FindCanonical(DnsDomain sname, out DnsClient.DNS.Records.CNAME cname)
        {
            IEnumerable <DnsClient.DNS.Records.CNAME> cnames = Response.AnswerRecords.Select <
                DnsClient.DNS.Records.CNAME>().Where(cn => sname.Equals(cn.Base.NAME));

            switch (cnames.Count())
            {
            case 0:
                cname = null;
                return(false);

            case 1:
                cname = cnames.First();
                return(true);

            default:
                // Ambigious CNAME records
                throw new QueryException(QueryState.AmbigiousCNAME, sname);
            }
        }
Example #21
0
        private static bool ValidateServerText(string text, out string errorMessage)
        {
            errorMessage = null;

            if (String.IsNullOrEmpty(text))
            {
                errorMessage = "Server name or address required.";
                return(false);
            }

            // IP address
            IPAddress ipaddr;

            if (IPAddress.TryParse(text, out ipaddr))
            {
                if (ipaddr.AddressFamily == AddressFamily.InterNetwork || ipaddr.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    return(true);
                }
                errorMessage = "Invalid IP address.";
                return(false);
            }

            // host name
            DnsDomain domain;

            if (DnsDomain.TryParse(text, out domain))
            {
                if (domain.Level >= 2)
                {
                    return(true);
                }
                errorMessage = "Invalid host name.";
                return(false);
            }

            errorMessage = "Invalid server name";
            return(false);
        }
Example #22
0
        private static bool ValidateNameText(string text, out string errorMessage)
        {
            errorMessage = null;

            if (String.IsNullOrEmpty(text))
            {
                errorMessage = "Domain name required.";
                return(false);
            }

            // host name
            DnsDomain domain;

            if (DnsDomain.TryParse(text, out domain))
            {
                if (domain.Level >= 1)
                {
                    return(true);
                }
            }

            errorMessage = "Invalid domain name.";
            return(false);
        }
Example #23
0
 public NameServer(DnsDomain zone, DnsDomain name, IEnumerable<IPAddress> addresses)
     : base(name, addresses)
 {
     this.Zone = zone;
 }
Example #24
0
 public NameServer(DnsDomain name)
     : base(name)
 {
     this.Zone = null;
 }
Example #25
0
 //private DnsClient.DNS.QTYPE GetAddressQuestion()
 //{
 //  switch (Resolver.Options.IPVersion)
 //  {
 //    case IPVersion.IPv4:
 //      return DnsClient.DNS.QTYPE.A;
 //    case IPVersion.IPv6:
 //      return DnsClient.DNS.QTYPE.AAAA;
 //    default:
 //      return DnsClient.DNS.QTYPE.ANY;
 //  }
 //}
 //private ResolutionIterator CreateSubIterator(DnsDomain domain, DnsClient.DNS.QTYPE question)
 //{
 //  ResolutionIterator iterator = new ResolutionIterator(this, domain, question);
 //  if (LogMessageCreated != null)
 //  {
 //    iterator.LogMessageCreated += new DnsClient.Logging.LogMessageEventHandler(OnSubIteratorLogMessage);
 //  }
 //  return iterator;
 //}
 private AddressIterator CreateAddressIterator(DnsDomain domain)
 {
     AddressIterator iterator = new Iterators.AddressIterator(this, domain, Resolver.Options.IPVersion);
       if (LogMessageCreated != null)
       {
     iterator.LogMessageCreated += new DnsClient.Logging.LogMessageEventHandler(OnSubIteratorLogMessage);
       }
       return iterator;
 }
Example #26
0
        /// <summary>
        /// Initialize a new instance of the Resolver class.
        /// </summary>
        /// <param name="options">Resolution options</param>
        /// <param name="domain">The domain in question</param>
        public DomainResolver(Options options, string domain)
        {
            if (object.ReferenceEquals(null, options))
            throw new ArgumentNullException("options");
              if (String.IsNullOrEmpty(domain))
            throw new ArgumentNullException("domain", "String value cannot be null or empty.");

              _Options = options;
              _Domain = (DnsDomain)domain;
        }
Example #27
0
 internal CNameIterator(ResolutionIterator iterator, DnsDomain domain)
     : base(new DomainResolver(iterator.Resolver.Options, domain),
            iterator.Question, iterator.AddressCache, iterator.NestingLevel + 1)
 {
 }
Example #28
0
 public TElement Get(DnsDomain domain)
 {
     return(Get(domain, DateTime.Now));
 }
Example #29
0
 public static LogMessage NextAuthoritiesReceived(DnsDomain server, DnsDomain name, NameServerCollection nextAuthorities)
 {
     return Create(Resources.LogMessages.NextAuthoritiesReceived,
     new object[] { server, name, nextAuthorities.Count });
 }
Example #30
0
 public static LogMessage NameServerResolved(NameServer resolved, DnsDomain domain)
 {
     return(Create(Resources.LogMessages.NameServerResolved, new object[] { resolved.Name, domain }));
 }
Example #31
0
 public static LogMessage StartingResultion(DnsDomain name)
 {
     return Create(Resources.LogMessages.StartingResultionRoot, new object[] { name });
 }
Example #32
0
 public static LogMessage NameServerResolved(NameServer resolved, DnsDomain domain)
 {
     return Create(Resources.LogMessages.NameServerResolved, new object[] { resolved.Name, domain });
 }
Example #33
0
 public static LogMessage ContinuingResultion(DnsDomain domain, NameServerCollection authorities)
 {
     return Create(Resources.LogMessages.ContinuingResultion, new object[] { domain, authorities.ZoneName });
 }
Example #34
0
 private NameServerCollection FindAuthorities(DnsDomain sname)
 {
     // NS RRs from Authority Section, resolved by Additional address RRs.
     return(NameServerCollection.Find(
                sname, Response.AuthorityRecords, Response.AdditionalRecords));
 }
Example #35
0
 public static LogMessage CNameFound(DnsDomain domain, string canonical)
 {
     return Create(Resources.LogMessages.CNameFound, new object[] { domain, canonical });
 }
Example #36
0
 public static LogMessage SingleAddressResolutionSucceeded(DnsDomain domain, System.Net.IPAddress address)
 {
     return Create(Resources.LogMessages.SingleAddressResolutionSucceeded, new object[] { domain, address });
 }
Example #37
0
        /// <summary>
        /// Initialize a new instance of the Resolver class using default options.
        /// </summary>
        /// <param name="domain">The domain in question</param>
        public DomainResolver(string domain)
        {
            if (String.IsNullOrEmpty(domain))
            throw new ArgumentNullException("domain", "String value cannot be null or empty.");

              _Options = Options.Default;
              _Domain = (DnsDomain)domain;
        }
Example #38
0
 public void Set(DnsDomain domain, IExpirableElement <TElement> element)
 {
     Data[domain] = element;
 }
Example #39
0
            public static LogMessage ResolutionSucceded(
        DnsDomain domain, DnsClient.DNS.QTYPE question, IEnumerable<DnsClient.DNS.RR> requestedAnswerRecords)
            {
                // must be true:
                // requestedAnswerRecords.Any()

                int count = requestedAnswerRecords.Count();
                if (count == 1)
                {
                  DnsClient.DNS.RR rr = requestedAnswerRecords.First();
                  DnsClient.DNS.Records.Address address;
                  DnsClient.DNS.Records.PTR pointer;

                  if (!Object.ReferenceEquals(null, (address = rr as DnsClient.DNS.Records.Address)))
                  {
                // "The name '{0}' was successfully resolved to {1}."
                return RESPONSE.INFO.SingleAddressResolutionSucceeded(domain, address.ADDRESS);
                  }

                  if (!Object.ReferenceEquals(null, (pointer = rr as DnsClient.DNS.Records.PTR)))
                  {
                // "Pointer resolution succeeded with the name '{0}'."
                return RESPONSE.INFO.SinglePointerResolutionSucceeded(pointer.PTRDNAME);
                  }

                  // "A Resouce Records of type {0} was found."
                  return RESPONSE.INFO.RecordResolutionSucceeded(question);
                }

                // "{1} Resouce Records of type {0} were found."
                return RESPONSE.INFO.RecordResolutionSucceeded(question, count);
            }
Example #40
0
 public static LogMessage ContinuingResultion(DnsDomain domain, NameServerCollection authorities)
 {
     return(Create(Resources.LogMessages.ContinuingResultion, new object[] { domain, authorities.ZoneName }));
 }
Example #41
0
 private NameServerCollection FindAuthorities(DnsDomain sname)
 {
     // NS RRs from Authority Section, resolved by Additional address RRs.
       return NameServerCollection.Find(
     sname, Response.AuthorityRecords, Response.AdditionalRecords);
 }
Example #42
0
 public static LogMessage StartingResultion(DnsDomain name, NameServerCollection authorities)
 {
     return(Create(Resources.LogMessages.StartingResultion, new object[] { name, authorities.ZoneName }));
 }
Example #43
0
        private bool FindCanonical(ref DnsDomain sname)
        {
            bool mapped = false;

              // Resolve CNAME chains within the zone itself
              DnsClient.DNS.Records.CNAME cname;
              List<DnsDomain> loopctrl = new List<DnsDomain>();
              while (FindCanonical(sname, out cname))
              {
            // name is an alias.
            if (sname.Equals(cname.CANONICAL))
            {
              // SERVER_ERROR
              // CName pointing to itself.
              throw new QueryException(QueryState.CNameSelf, sname);
            }
            if (loopctrl.Contains(sname))
            {
              // SERVER_ERROR
              // Loop detected in local CNAME chain.
              throw new QueryException(QueryState.LocalCNameLoop, sname);
            }

            DnsDomain canonical = (DnsDomain)cname.CANONICAL;
            LogMessageCreate(Logging.LogMessageText.RESPONSE.WARN.CNameFound(sname, canonical));
            sname = canonical;
            loopctrl.Add((DnsDomain)cname.CANONICAL);
            mapped = true;
              }
              return mapped;
        }
Example #44
0
        /// <summary>
        /// Initialize a new instance of the Resolver class using default options.
        /// </summary>
        /// <param name="domain">The domain in question</param>
        public DomainResolver(DnsDomain domain)
        {
            if (object.ReferenceEquals(null, domain))
            throw new ArgumentNullException("domain");

              _Options = Options.Default;
              _Domain = domain;
        }
Example #45
0
 private bool FindCanonical(DnsDomain sname, out DnsClient.DNS.Records.CNAME cname)
 {
     IEnumerable<DnsClient.DNS.Records.CNAME> cnames = Response.AnswerRecords.Select<
     DnsClient.DNS.Records.CNAME>().Where(cn => sname.Equals(cn.Base.NAME));
       switch (cnames.Count())
       {
     case 0:
       cname = null;
       return false;
     case 1:
       cname = cnames.First();
       return true;
     default:
       // Ambigious CNAME records
       throw new QueryException(QueryState.AmbigiousCNAME, sname);
       }
 }
Example #46
0
        protected virtual void OnCNameFound(DnsDomain cname)
        {
            // "The name '{0}' is an alias for the canonical name '{1}'."
              LogMessageCreate(Logging.LogMessageText.RESPONSE.WARN.CNameFound(Resolver.Domain, cname));

              if (!Resolver.Options.FollowCanonical)
              {
            // "The resolver is not configured to follow the canonical name."
            LogMessageCreate(Logging.LogMessageText.RESPONSE.WARN.CNameNoFollow());
              }
        }
Example #47
0
 public QueryProcessor(DnsDomain sname, DnsClient.DNS.QTYPE stype, DnsClient.Response response)
 {
     this.SNAME = sname;
       this.STYPE = stype;
       this.Response = response;
 }
Example #48
0
        private Iterators.CNameIterator CreateCNameIterator(DnsDomain cname, NameServerCollection authorities)
        {
            // TODO
              // apply authorties

              Iterators.CNameIterator iterator = new CNameIterator(this, (DnsDomain)cname);
              if (LogMessageCreated != null)
              {
            iterator.LogMessageCreated += new DnsClient.Logging.LogMessageEventHandler(OnSubIteratorLogMessage);
              }
              return iterator;
        }
Example #49
0
 internal AddressIterator(ResolutionIterator iterator, DnsDomain domain, IPVersion ipVersion)
     : base(new DomainResolver(iterator.Resolver.Options, domain),
            GetAddressQuestion(ipVersion), iterator.AddressCache, iterator.NestingLevel + 1)
 {
 }
Example #50
0
 //public NameServer(string name)
 //  : base(name)
 //{
 //  this.Zone = null;
 //}
 //public NameServer(DnsDomain name, IEnumerable<IPAddress> addresses)
 //  : base(name, addresses)
 //{
 //}
 public NameServer(DnsDomain zone, DnsDomain name)
     : base(name)
 {
     this.Zone = zone;
 }
Example #51
0
        public QueryResult Process()
        {
            // [RFC 1034], 5.3.3. Algorithm
            //
            // 4. Analyze the response, either:
            //
            //   a. if the response answers the question or contains a name
            //     error, cache the data as well as returning it back to
            //     the client.
            //
            //   b. if the response contains a better delegation to other
            //     servers, cache the delegation information, and go to
            //     step 2.
            //
            //   c. if the response shows a CNAME and that is not the
            //     answer itself, cache the CNAME, change the SNAME to the
            //     canonical name in the CNAME RR and go to step 1.
            //
            //   d. if the response shows a servers failure or other
            //     bizarre contents, delete the server from the SLIST and
            //     go back to step 3.
            //
            // Step 4 involves analyzing responses.  The resolver should be highly
            // paranoid in its parsing of responses.



            // Verify the question section matches the query.
            if (Response.Questions.Count == 1)
            {
                DnsClient.DNS.Question q = Response.Questions.First();
                if (!this.SNAME.Equals(q.QNAME) || this.STYPE != q.QTYPE)
                {
                    throw new QueryException(QueryState.MissingQuestion);
                }
            }
            else
            {
                throw new QueryException(QueryState.MissingQuestion);
            }

            // Check for unhandled RCODE.
            if (!(Response.Header.RCODE == DnsClient.DNS.RCODE.NoError ||
                  Response.Header.RCODE == DnsClient.DNS.RCODE.NameError))
            {
                return(new QueryResult {
                    State = QueryState.UnexpectedRCode
                });
            }

            // RCODE.NoError or RCODE.NameError

            if (!Response.Header.AA)
            {
                // Non-Authoritative Answer

                NameServerCollection nextAuthorities = FindAuthorities(SNAME);
                if (nextAuthorities.Any())
                {
                    // Referral response: authorities is not empty.

                    // Check for relevant answer RRs matching STYPE within additional RRs
                    IEnumerable <DnsClient.DNS.RR> additional = Response.AdditionalRecords.Where(
                        rr => SNAME.Equals(rr.Base.NAME)).OfQuestion(STYPE);
                    if (additional.Any())
                    {
                        // Found answer RRs matching the query.
                        return(new QueryResult
                        {
                            Answers = additional,
                            State = QueryState.NonAuthoritativeAnswer
                        });
                    }

                    return(new QueryResult
                    {
                        NextAuthorities = nextAuthorities,
                        State = QueryState.NextAuthorities
                    });
                }

                return(new QueryResult {
                    State = QueryState.MissingAuthorities
                });
            }

            // Authoritative Answer

            // Process CNAMEs unless the question is CNAME.
            // Even on RCODE.NameError CNAMEs need to be applied
            // (cf.: [RFC 2308], 2.1 - Name Error).
            bool      cnamed    = false;
            DnsDomain canonical = SNAME;

            if (STYPE != DnsClient.DNS.QTYPE.CNAME)
            {
                // resolve internal CNAME chain
                cnamed = FindCanonical(ref canonical);
            }

            if (Response.Header.RCODE == DnsClient.DNS.RCODE.NameError)
            {
                // RCODE.NameError

                // [RFC 2308], 2.1 - Name Error
                //
                // Name errors (NXDOMAIN) are indicated by the presence of "Name Error"
                // in the RCODE field.  In this case the domain referred to by the QNAME
                // does not exist.  Note: the answer section may have SIG and CNAME RRs
                // and the authority section may have SOA, NXT [RFC2065] and SIG RRsets.
                //
                // It is possible to distinguish between a referral and a NXDOMAIN
                // response by the presense of NXDOMAIN in the RCODE regardless of the
                // presence of NS or SOA records in the authority section.

                return(new QueryResult
                {
                    CanonicalName = cnamed ? canonical : null,
                    SOA = Response.AuthorityRecords.FirstOrDefault <
                        DnsClient.DNS.Records.SOA>(),
                    State = QueryState.NxDomain
                });
            }

            // Authoritative RCODE.NoError

            // Check for relevant answer RRs matching the canonical name and STYPE.
            IEnumerable <DnsClient.DNS.RR> answers = Response.AnswerRecords.Where(
                rr => canonical.Equals(rr.Base.NAME)).OfQuestion(STYPE);

            if (answers.Any())
            {
                // Found answer RRs matching the query.
                return(new QueryResult
                {
                    CanonicalName = cnamed ? canonical : null,
                    Answers = answers,
                    State = QueryState.AuthoritativeAnswer
                });
            }

            // NoData or referral CNAME response

            // [RFC 2308], 2.2 - No Data
            //
            // It is possible to distinguish between a NODATA and a referral
            // response by the presence of a SOA record in the authority section or
            // the absence of NS records in the authority section.

            DnsClient.DNS.Records.SOA soa = Response.AuthorityRecords.FirstOrDefault <
                DnsClient.DNS.Records.SOA>();
            NameServerCollection authorities = FindAuthorities(canonical);

            if (!object.ReferenceEquals(null, soa) || authorities.Any())
            {
                // NODATA
                // Do not treat as referral (cf.: [RFC 2308], 2.2 - No Data)
                return(new QueryResult
                {
                    SOA = soa,
                    CanonicalName = cnamed ? canonical : null,
                    State = QueryState.NoData
                });
            }

            // Referral response: authorities is not empty.

            if (cnamed)
            {
                // referral CNAME
                return(new QueryResult
                {
                    CanonicalName = canonical,
                    NextAuthorities = FindAuthorities(canonical),
                    State = QueryState.FollowCName
                });
            }

            return(new QueryResult {
                State = QueryState.EmptyResponse
            });
        }
Example #52
0
 internal DomainResolver(DomainResolver resolver, DnsDomain domain)
 {
     _Options = resolver.Options;
       _Domain = domain;
 }
Example #53
0
   internal AddressIterator(ResolutionIterator iterator, DnsDomain domain, IPVersion ipVersion)
       : base(new DomainResolver(iterator.Resolver.Options, domain),
 GetAddressQuestion(ipVersion), iterator.AddressCache, iterator.NestingLevel + 1)
   {
   }
Example #54
0
   internal CNameIterator(ResolutionIterator iterator, DnsDomain domain)
       : base(new DomainResolver(iterator.Resolver.Options, domain), 
 iterator.Question, iterator.AddressCache, iterator.NestingLevel + 1)
   {
   }
Example #55
0
 public void Set(DnsDomain domain, TElement element)
 {
     Set(domain, new ExpirableElement <TElement>(element));
 }
Example #56
0
        static void Main(string[] args)
        {
            try
            {
                File.Delete(filename);

                bool interactive = false;

                NameServer selected = null;
                while (true)
                {
                    if (File.Exists(filename))
                    {
                        using (DnsUdpClient client = new DnsUdpClient())
                        {
                            client.Client.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket, System.Net.Sockets.SocketOptionName.ReceiveTimeout, 1000);

                            client.LogMessageCreated += new LogMessageEventHandler(OnLogMessage);
                            ResolutionIterator iterator = DeSerializeObject <ResolutionIterator>(filename);

                            iterator.Resolver.Connect(client);
                            if (iterator.MoveNext(selected))
                            {
                                Console.WriteLine();

                                ResolutionResult result = iterator.Current;

                                //Console.WriteLine("Response from {0} - chosen from {1} authorities", result.Authorities.Selected.Name, result.Authorities.ZoneName);
                                //foreach (NameServer ns in result.Authorities)
                                //{
                                //  Console.WriteLine("  {0}", ns);
                                //}

                                Console.WriteLine("Took {0}ms:", result.Duration.TotalMilliseconds);
                                RenderResponse(result.Response);

                                if (interactive)
                                {
                                    selected = null;
                                    if (result.NextAuthorities != null)
                                    {
                                        Console.WriteLine();
                                        Console.WriteLine("Next authorities:");
                                        int i = 1;
                                        foreach (NameServer ns in result.NextAuthorities)
                                        {
                                            Console.WriteLine("  ({0}) {1}", i, ns.ToString());
                                            i++;
                                        }

                                        while (true)
                                        {
                                            Console.Write("Select next authority or ENTER for random: ");
                                            int    s;
                                            string choice = Console.ReadLine();
                                            if (!String.IsNullOrEmpty(choice))
                                            {
                                                if (int.TryParse(choice, out s))
                                                {
                                                    if (s >= 1 && s <= result.NextAuthorities.Count)
                                                    {
                                                        selected = result.NextAuthorities[s - 1];
                                                        break;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                break;
                                            }
                                        }
                                    }
                                }

                                SerializeObject <ResolutionIterator>(filename, iterator);
                                Console.WriteLine("====================================");
                            }
                            else
                            {
                                Console.WriteLine("finished.");
                                File.Delete(filename);
                            }
                        }
                    }
                    else
                    {
                        DnsDomain domain = null;
                        QTYPE     question;

                        try
                        {
                            Console.Write("enter name: ");
                            domain = DnsDomain.Parse(Console.ReadLine().Trim());
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            goto next;
                        }

                        try
                        {
                            Console.Write("enter question: ");
                            question = (QTYPE)Enum.Parse(typeof(QTYPE), Console.ReadLine().Trim(), true);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            goto next;
                        }

                        Console.WriteLine("OK: {0} IN {1}", domain, question.ToString());

                        DomainResolver     resolver = new DomainResolver(Options.Default, domain);
                        ResolutionIterator iterator = resolver.GetIterator(question);
                        iterator.LogMessageCreated += new LogMessageEventHandler(OnLogMessage);

                        SerializeObject <ResolutionIterator>(filename, iterator);
                    }

next:
                    Console.WriteLine();
                    Console.WriteLine("type 'q' to quit, ENTER to continue.");
                    ConsoleKeyInfo ck = Console.ReadKey();
                    if (ck.KeyChar == 'q')
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
Example #57
0
 public static LogMessage NameNotExisting(DnsDomain domain)
 {
     return Create(Resources.LogMessages.NameNotExisting, new object[] { domain });
 }
Example #58
0
 public static LogMessage StartingResultion(DnsDomain name, NameServerCollection authorities)
 {
     return Create(Resources.LogMessages.StartingResultion, new object[] { name, authorities.ZoneName });
 }
Example #59
0
 public QueryProcessor(DnsDomain sname, DnsClient.DNS.QTYPE stype, DnsClient.Response response)
 {
     this.SNAME    = sname;
     this.STYPE    = stype;
     this.Response = response;
 }