public void TestNoSubzoneAuthoritative() { // Ensures that we don't return a subzone for things we're directly an // authority for var zone = new DNSZone(start_of_authority, relays); Assert.That(zone.FindSubZone(new Domain("www.example.com")), Is.Null); }
public void TestNoSubzoneNotAuthoritatie() { // Ensures that we don't return a subzone for things that are outside of // our authority var zone = new DNSZone(start_of_authority, relays); Assert.That(zone.FindSubZone(new Domain("bogus.com")), Is.Null); }
public void TestSubzoneWithDelegation() { // Ensure that we can find the subzone for a domain in that subzone var zone = new DNSZone(start_of_authority, relays); var subzone = new DNSRecord( new Domain("foo.example.com"), AddressClass.INTERNET, 42, new NSResource(new Domain("ns.foo.example.com"))); zone.Add(subzone); Assert.That(zone.FindSubZone(new Domain("www.foo.example.com")), Is.EqualTo(new Domain("foo.example.com"))); }
/** * Resolves the given query, returning a QueryResult that contains * everything we found while doing the resolution. */ public QueryResult Execute(Domain domain, ResourceRecordType rtype, AddressClass addr_class, bool recursive) { logger.Trace("Executing query on {0} for type {1} with recursion {2}", domain, rtype, recursive); if (zone.IsAuthorityFor(domain)) { var records = zone.Query(domain, rtype, addr_class).ToList(); // It is possible that there is a CNAME that we should be aware of - in that case, check // it and see if we can find one. if (records.Count == 0) { var cname_records = zone.Query(domain, ResourceRecordType.CANONICAL_NAME, addr_class).ToArray(); if (cname_records.Length != 0) { logger.Trace("Authoritative for CNAMEs, re-executing"); // In this case, try again with the alias var alias = ((CNAMEResource)cname_records[0].Resource).Alias; var alias_results = Execute(alias, rtype, addr_class, recursive); // The RFC directs us to return any intermediate CNAMEs, which we do alias_results.Answers.InsertRange(0, cname_records); return(alias_results); } } var result = new QueryResult(); result.IsAuthority = true; result.FoundAnswer = true; result.Answers = new List <DNSRecord>(); result.Authority = new List <DNSRecord>(); result.Additional = new List <DNSRecord>(); result.Answers.AddRange(records); result.Authority.Add(zone.StartOfAuthority); return(result); } else { var owning_subzone = zone.FindSubZone(domain); if (owning_subzone != null) { logger.Trace("Subzone {0} is authoritative", owning_subzone); // We can punt on the computation to our subzone delgation var subzone_nameservers = zone.Query(owning_subzone, ResourceRecordType.NAME_SERVER, addr_class); var subzone_nameserver_addr_records = subzone_nameservers .SelectMany(ns => zone.Query(ns.Name, ResourceRecordType.HOST_ADDRESS, addr_class)); var subzone_nameserver_addrs = subzone_nameserver_addr_records.Select( record => new IPEndPoint(((AResource)record.Resource).Address, 53) ).ToArray(); IEnumerable <DNSRecord> response = null; try { var info = resolver.Resolve(domain, ResourceRecordType.HOST_ADDRESS, addr_class, subzone_nameserver_addrs); response = info.aliases.Concat(info.answers).ToList(); } catch (ResolverException err) { logger.Trace("Could not resolve from subzone: {0}", err); response = new DNSRecord[] { }; } var result = new QueryResult(); result.IsAuthority = false; result.FoundAnswer = response.Count() > 0; result.Answers = new List <DNSRecord>(response); result.Authority = new List <DNSRecord>(subzone_nameservers); result.Additional = new List <DNSRecord>(subzone_nameserver_addr_records); return(result); } else if (recursive) { // We'll have to go outside our zone and use the general-purpose resolver ResolverResult response; logger.Trace("No authoritative server is local, executing recursive resolver"); try { response = resolver.Resolve(domain, rtype, addr_class, zone.Relays); } catch (ResolverException err) { logger.Trace("Could not resolve: {0}", err); response = new ResolverResult(); response.answers = new List <DNSRecord>(); response.aliases = new List <DNSRecord>(); response.referrals = new List <DNSRecord>(); response.referral_additional = new List <DNSRecord>(); } var result = new QueryResult(); result.IsAuthority = false; result.FoundAnswer = response.answers.Count() > 0; result.Answers = response.aliases.Concat(response.answers).ToList(); result.Authority = response.referrals.ToList(); result.Additional = response.referral_additional.ToList(); return(result); } else { var cached_responses = cache.Query(domain, AddressClass.INTERNET, rtype); if (cached_responses.Count > 0) { logger.Trace("Non-recursive search found {0} cached results", cached_responses.Count); var cached_result = new QueryResult(); cached_result.IsAuthority = false; cached_result.FoundAnswer = true; cached_result.Answers = cached_responses.ToList(); cached_result.Additional = new List <DNSRecord>(); cached_result.Authority = new List <DNSRecord>(); return(cached_result); } // If we can't recurse, and our cache knows nothing, then punt onto the forwarder logger.Trace("Executing limited-case non-recursive resolver"); var question = new DNSQuestion(domain, rtype, AddressClass.INTERNET); foreach (var forwarder in zone.Relays) { try { var forward_result = ResolverUtils.SendQuery(forwarder, question, false); // If the server doesn't like our request, then pass it to something else if (forward_result.ResponseType != ResponseType.NO_ERROR && forward_result.ResponseType != ResponseType.NAME_ERROR) { continue; } var forward_return = new QueryResult(); forward_return.FoundAnswer = forward_result.ResponseType == ResponseType.NO_ERROR; forward_return.IsAuthority = false; forward_return.Answers = forward_result.Answers.ToList(); forward_return.Additional = forward_result.AdditionalRecords.ToList(); forward_return.Authority = forward_result.AuthoritativeAnswers.ToList(); return(forward_return); } catch (SocketException err) { // We can safely punt onto the next forwarder if one bails logger.Trace("Could not request from {0}: {1}", forwarder, err); } } // We can't do anything else here, so there is no such host, as far as we knot var result = new QueryResult(); result.FoundAnswer = false; result.IsAuthority = false; result.Answers = new List <DNSRecord>(); result.Authority = new List <DNSRecord>(); result.Additional = new List <DNSRecord>(); return(result); } } }