public void TestStubResolverAcceptsSeveralAliasesForAAAARecords() { // Make sure that chains of aliases are supported var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.HOST_6ADDRESS, AddressClass.INTERNET); var expected_alias_answer_1 = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new CNAMEResource(new Domain("www.example.com"))); var expected_alias_answer_2 = new DNSRecord( new Domain("www.example.com"), AddressClass.INTERNET, 42, new CNAMEResource(new Domain("web1.www.example.com"))); var expected_addr_answer = new DNSRecord( new Domain("web1.www.example.com"), AddressClass.INTERNET, 42, new AAAAResource(IPv6Address.Parse("2001:cafe:beef::"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[] { expected_alias_answer_1, expected_alias_answer_2, expected_addr_answer }, new DNSRecord[0], new DNSRecord[0]); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.HOST_6ADDRESS, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[] { expected_addr_answer }; expected_result.aliases = new DNSRecord[] { expected_alias_answer_1, expected_alias_answer_2 }; expected_result.referrals = new DNSRecord[0]; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverAcceptsSOARecords() { // The same as the previous test, but this makes sure that less common // record types are still recognized as answers for the appropriate queries var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.START_OF_AUTHORITY, AddressClass.INTERNET); var expected_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new SOAResource( new Domain("ns.example.com"), new Domain("hostmaster.example.com"), 0, 360, 360, 360, 360)); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[] { expected_answer }, new DNSRecord[0], new DNSRecord[0]); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.START_OF_AUTHORITY, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[] { expected_answer }; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[0]; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverReturnsRedirectionsWithAAAAResourceGlue() { // Make sure that any redirections are returned, even if there aren't any actual // results, along with their glue if provided var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET); var expected_ns_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new NSResource(new Domain("ns.example.com"))); var expected_glue_answer = new DNSRecord( new Domain("ns.example.com"), AddressClass.INTERNET, 42, new AAAAResource(IPv6Address.Parse("2001:cafe:beef::"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[0], new DNSRecord[] { expected_ns_answer }, new DNSRecord[] { expected_glue_answer }); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[0]; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[] { expected_ns_answer }; expected_result.referral_additional = new DNSRecord[] { expected_glue_answer }; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverSequenceOfRelays() { // Make sure that the resolver ignores failing resolvers, as long as at least one succeeds var good_relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var bad_relay = new IPEndPoint(IPAddress.Parse("192.168.0.2"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET); var expected_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new AResource(IPv4Address.Parse("192.168.0.1"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[] { expected_answer }, new DNSRecord[0], new DNSRecord[0]); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { if (target.Equals(bad_relay)) { throw new SocketException(); } Assert.That(target, Is.EqualTo(good_relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET, new EndPoint[] { bad_relay, good_relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[] { expected_answer }; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[0]; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverRejectsIrrelevantGlue() { // Make sure that any redirections are returned, but rejects any bad glue var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET); var expected_ns_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new NSResource(new Domain("ns.example.com"))); var unexpected_glue_answer = new DNSRecord( new Domain("ns2.example.com"), AddressClass.INTERNET, 42, new AResource(IPv4Address.Parse("192.168.0.2"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[0], new DNSRecord[] { expected_ns_answer }, new DNSRecord[] { unexpected_glue_answer }); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[0]; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[] { expected_ns_answer }; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverAcceptsARecords() { // The idea behind this test is to make sure that direct answers to the question are accpted // (no CNAMEs, no referrals, etc.). A records are the most common query, so they are a good // starting point. var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET); var expected_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new AResource(IPv4Address.Parse("192.168.0.1"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[] { expected_answer }, new DNSRecord[0], new DNSRecord[0]); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[] { expected_answer }; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[0]; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverRecordsCNAMEAnswers() { // This ensures that any request for a CNAME to a paritcular domain ends up in the answers // list (and only the answers list) if we're asking for CNAMEs var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.CANONICAL_NAME, AddressClass.INTERNET); var expected_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new CNAMEResource(new Domain("www.example.com"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[] { expected_answer }, new DNSRecord[0], new DNSRecord[0]); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.CANONICAL_NAME, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[] { expected_answer }; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[0]; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
/** * Does the actual work of resolution, by talking to all the servers and * interpreting their answers. */ public ResolverResult Resolve(Domain domain, ResourceRecordType rtype, AddressClass addr_class, EndPoint[] servers) { var records = cache.Query(domain, addr_class, rtype); if (records.Count == 0) { var packet = QueryServers(domain, rtype, addr_class, servers); int found = 0; foreach (var resource in packet.Answers) { if (resource.Resource != null) { records.Add(resource); cache.Add(resource); found++; } } logger.Trace("Found {0} answers", found); found = 0; foreach (var resource in packet.AdditionalRecords) { if (resource.Resource != null) { records.Add(resource); cache.Add(resource); } found++; } logger.Trace("Found {0} additional records", found); found = 0; foreach (var resource in packet.AuthoritativeAnswers) { if (resource.Resource != null) { records.Add(resource); cache.Add(resource); } found++; } logger.Trace("Found {0} authoritative record", found); } else { logger.Trace("Cache returned {0} resources", records.Count); } var any_results = false; var results = new List <DNSRecord>(); var aliases = new HashSet <Domain>(); var nameservers = new HashSet <Domain>(); var nameserver_addrs = new HashSet <IPAddress>(); var alias_rrs = new List <DNSRecord>(); var nameserver_rrs = new List <DNSRecord>(); var nameserver_addr_rrs = new List <DNSRecord>(); // We'll attack this in stages - first, record all the CNAMEs for the current domain // (But only if we're looking specifically for A records - other records // generally can't have aliases). Here, we're hoping that the server gives us the addresses // in what is basically a topologically sorted order (think of chained CNAMEs as a graph). if (rtype == ResourceRecordType.HOST_ADDRESS || rtype == ResourceRecordType.HOST_6ADDRESS) { foreach (var record in records) { var is_relevant = record.Name == domain || aliases.Contains(record.Name); if (record.Resource != null && record.Resource.Type == ResourceRecordType.CANONICAL_NAME && is_relevant) { logger.Trace("Recording alias {0}", record); aliases.Add(((CNAMEResource)record.Resource).Alias); alias_rrs.Add(record); any_results = true; } } } // Next, fish out any addresses that answer the query foreach (var record in records) { var is_relevant = record.Name == domain || aliases.Contains(record.Name); if (record.Resource != null && record.Resource.Type == rtype && is_relevant) { logger.Trace("Recording relevant answer {0}", record); results.Add(record); any_results = true; } } // Finally, get any referrals or authority claims that we're given foreach (var record in records) { if (record.Resource != null && record.Resource.Type == ResourceRecordType.NAME_SERVER) { logger.Trace("Recording nameserver {0}", record); nameservers.Add(((NSResource)record.Resource).Nameserver); nameserver_rrs.Add(record); any_results = true; } } // If the server was helpful enough to give us some glue, then make sure // to record them as well foreach (var record in records) { if (record.Resource != null && (record.Resource.Type == ResourceRecordType.HOST_ADDRESS || record.Resource.Type == ResourceRecordType.HOST_6ADDRESS) && nameservers.Contains(record.Name)) { logger.Trace("Recording nameserver glue {0}", record); switch (record.Resource.Type) { case ResourceRecordType.HOST_ADDRESS: nameserver_addrs.Add(((AResource)record.Resource).Address); break; case ResourceRecordType.HOST_6ADDRESS: nameserver_addrs.Add(((AAAAResource)record.Resource).Address); break; } nameserver_addr_rrs.Add(record); any_results = true; } } if (!any_results) { throw new ResolverException(domain, "Did not get any records relevant to " + domain); } var result = new ResolverResult(); result.answers = results; result.aliases = alias_rrs; result.referrals = nameserver_rrs; result.referral_additional = nameserver_addr_rrs; return(result); }