コード例 #1
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestMinimumConfigFile()
        {
            // The smallest file that you can get away with is an empty zone, which has just an SOA
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""7200"" 
         primary-ns=""ns.example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />
</zone>
			"            );

            var zone = DNSZone.Unserialize(config);

            Assert.That(zone.Relays, Is.Empty);

            Assert.That(zone.StartOfAuthority, Is.EqualTo(
                            new DNSRecord(
                                new Domain("example.com"),
                                AddressClass.INTERNET,
                                7200,
                                new SOAResource(
                                    new Domain("ns.example.com"),
                                    new Domain("admin.example.com"),
                                    0,
                                    3600,
                                    60,
                                    3600,
                                    60))));
        }
コード例 #2
0
        public static void Main(string[] args)
        {
            if (args.Length != 3)
            {
                Console.WriteLine("Usage: dns-server <config-file> <ip-address> <port>");
                Environment.Exit(1);
            }

            var config = new XmlDocument();

            config.Load(args[0]);

            var zone       = DNSZone.Unserialize(config);
            var clock      = new StopwatchClock();
            var cache      = new ResolverCache(clock, 2048);
            var resolver   = new StubResolver(cache, ResolverUtils.SendQuery);
            var query_exec = new QueryExecutor(zone, resolver, cache);

            var bind_addr = new IPEndPoint(IPAddress.Parse(args[1]),
                                           int.Parse(args[2]));

            var server = new UDPServer(bind_addr, query_exec);

            server.Start();
        }
コード例 #3
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestNotAuthorityWhenPTRIsUnknown()
        {
            // We can't be authorities for PTR records we don't recognize
            var zone = new DNSZone(start_of_authority, relays);

            Assert.That(zone.IsAuthorityFor(new Domain("1.0.168.192.in-addr.arpa")), Is.False);
        }
コード例 #4
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestEmptyConfigFileFails()
        {
            // The empty configuration file is not valid, since it lacks a SOA
            var config = ParseXML("<zone></zone>");

            Assert.Throws <InvalidDataException>(() => DNSZone.Unserialize(config));
        }
コード例 #5
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestNotAuthorityWithoutDelegation()
        {
            // Ensure that we are not considered authoritative for things clearly
            // outside of our zone
            var zone = new DNSZone(start_of_authority, relays);

            Assert.That(zone.IsAuthorityFor(new Domain("bogus.com")), Is.False);
        }
コード例 #6
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        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);
        }
コード例 #7
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestAuthorityWithoutDelegation()
        {
            // Ensure that we are considered authoritative for things that
            // are in our zone (without involvement by subzones)
            var zone = new DNSZone(start_of_authority, relays);

            Assert.That(zone.IsAuthorityFor(new Domain("www.example.com")), Is.True);
        }
コード例 #8
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        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);
        }
コード例 #9
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestSOABadPrimaryNS()
        {
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""3600"" 
         primary-ns=""....example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />
</zone>
			"            );

            Assert.Throws <InvalidDataException>(() => DNSZone.Unserialize(config));
        }
コード例 #10
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestSOAMissingMinTTL()
        {
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""3600"" 
         primary-ns=""ns.example.com"" hostmaster=""hostmaster.example.com""
         refresh=""3600"" retry=""3600"" expire=""3600"" />
</zone>
			"            );

            Assert.Throws <InvalidDataException>(() => DNSZone.Unserialize(config));
        }
コード例 #11
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestHighTTLFails()
        {
            // TTLs are 32-bit numbers, so any TTL over 136 years doesn't work
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""9999999999"" 
         primary-ns=""ns.example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />
</zone>
			"            );

            Assert.Throws <InvalidDataException>(() => DNSZone.Unserialize(config));
        }
コード例 #12
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestAuthorityWhenPTRIsKnownV6()
        {
            // We should be an authority for a PTR record that we know about
            var zone = new DNSZone(start_of_authority, relays);
            var ptr  = new DNSRecord(
                new Domain("b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa"),
                AddressClass.INTERNET,
                42,
                new PTRResource(new Domain("www.example.com")));

            zone.Add(ptr);

            Assert.That(zone.IsAuthorityFor(new Domain("b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa")), Is.True);
        }
コード例 #13
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestRelayTooHighPort()
        {
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""7200"" 
         primary-ns=""ns.example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />

	<relay address=""192.168.0.1"" port=""1000000"" />
</zone>
			"            );

            Assert.Throws <InvalidDataException>(() => DNSZone.Unserialize(config));
        }
コード例 #14
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestPTRMissingPointer()
        {
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""3600"" 
         primary-ns=""ns.example.com"" hostmaster=""hostmaster.example.com""
         refresh=""3600"" retry=""3600"" expire=""3600"" />

	<PTR name=""1.0.168.192.in-addr.arpa"" class=""IN"" ttl=""3600"" />
</zone>
			"            );

            Assert.Throws <InvalidDataException>(() => DNSZone.Unserialize(config));
        }
コード例 #15
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestMXGarbageMailserver()
        {
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""3600"" 
         primary-ns=""ns.example.com"" hostmaster=""hostmaster.example.com""
         refresh=""3600"" retry=""3600"" expire=""3600"" />

	<MX name=""example.com"" class=""IN"" ttl=""3600"" priority=""1"" mailserver="".....example.com"" />
</zone>
			"            );

            Assert.Throws <InvalidDataException>(() => DNSZone.Unserialize(config));
        }
コード例 #16
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestAuthorityWithDelegation()
        {
            // Ensures that we're not an authority for things that are subzones
            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.IsAuthorityFor(new Domain("www.foo.example.com")), Is.False);
        }
コード例 #17
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestAIPv6Address()
        {
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""3600"" 
         primary-ns=""ns.example.com"" hostmaster=""hostmaster.example.com""
         refresh=""3600"" retry=""3600"" expire=""3600"" />

	<A name=""example.com"" class=""IN"" ttl=""3600"" address=""2001:beef:cafe::1337"" />
</zone>
			"            );

            Assert.Throws <InvalidDataException>(() => DNSZone.Unserialize(config));
        }
コード例 #18
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestAuthorityWhenEqualToDelegation()
        {
            // Ensure that we are an authority for the subzone's address itself (which can
            // occur if, say, there's a CNAME pointing to it)
            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.IsAuthorityFor(new Domain("foo.example.com")), Is.True);
        }
コード例 #19
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        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")));
        }
コード例 #20
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestRelayGarbagePort()
        {
            // The smallest file that you can get away with is an empty zone, which has just an SOA
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""7200"" 
         primary-ns=""ns.example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />

	<relay address=""192.168.0.1"" port=""blargh"" />
</zone>
			"            );

            Assert.Throws <InvalidDataException>(() => DNSZone.Unserialize(config));
        }
コード例 #21
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestMultipleSOAFails()
        {
            // Multiple SOA records are not allowed, since we currently don't support multiple zones
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""7200"" 
         primary-ns=""ns.example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />

	<SOA name=""fabrikam.com"" class=""IN"" ttl=""7200"" 
         primary-ns=""ns.example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />
</zone>
			"            );

            Assert.Throws <InvalidDataException>(() => DNSZone.Unserialize(config));
        }
コード例 #22
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestQuery()
        {
            var zone         = new DNSZone(start_of_authority, relays);
            var www_a_record = new DNSRecord(
                new Domain("www.example.com"),
                AddressClass.INTERNET,
                42,
                new AResource(IPv4Address.Parse("192.168.0.1")));

            var www_a_record_2 = new DNSRecord(
                new Domain("www.example.com"),
                AddressClass.INTERNET,
                42,
                new AResource(IPv4Address.Parse("192.168.0.2")));

            // Something that matches the class and record type, but not the domain
            var www2_a_record = new DNSRecord(
                new Domain("www2.example.com"),
                AddressClass.INTERNET,
                42,
                new AResource(IPv4Address.Parse("192.168.0.3")));

            // Something that matches the domain and class, but not the record type
            var www_cname_record = new DNSRecord(
                new Domain("www.example.com"),
                AddressClass.INTERNET,
                42,
                new CNAMEResource(new Domain("www2.example.com")));

            zone.Add(www_a_record);
            zone.Add(www_a_record_2);
            zone.Add(www2_a_record);
            zone.Add(www_cname_record);

            var query_result = zone.Query(
                new Domain("www.example.com"),
                ResourceRecordType.HOST_ADDRESS,
                AddressClass.INTERNET);

            var expected = new List <DNSRecord>();

            expected.Add(www_a_record);
            expected.Add(www_a_record_2);
            Assert.That(query_result, Is.EquivalentTo(expected));
        }
コード例 #23
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestConfigRelay()
        {
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""7200"" 
         primary-ns=""ns.example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />

	<relay address=""192.168.0.1"" port=""53"" />
</zone>
			"            );

            var zone   = DNSZone.Unserialize(config);
            var relays = new EndPoint[] {
                new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53)
            };

            Assert.That(zone.Relays, Is.EquivalentTo(relays));
        }
コード例 #24
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestConfigMXRecord()
        {
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""7200"" 
         primary-ns=""ns.example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />

    <MX name=""example.com"" class=""IN"" ttl=""3600"" priority=""42"" mailserver=""smtp.example.com"" />
</zone>
			"            );

            var zone = DNSZone.Unserialize(config);

            var records = new List <DNSRecord>();

            records.Add(new DNSRecord(
                            new Domain("example.com"),
                            AddressClass.INTERNET,
                            3600,
                            new MXResource(42, new Domain("smtp.example.com"))));

            Assert.That(zone.Records, Is.EquivalentTo(records));
        }
コード例 #25
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestConfigAAAARecord()
        {
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""7200"" 
         primary-ns=""ns.example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />

    <AAAA name=""www.example.com"" class=""IN"" ttl=""3600"" address=""2001:0DB8:AC10:FE01:0000:0000:0000:0000"" />
</zone>
			"            );

            var zone = DNSZone.Unserialize(config);

            var records = new List <DNSRecord>();

            records.Add(new DNSRecord(
                            new Domain("www.example.com"),
                            AddressClass.INTERNET,
                            3600,
                            new AAAAResource(IPv6Address.Parse("2001:0DB8:AC10:FE01:0000:0000:0000:0000"))));

            Assert.That(zone.Records, Is.EquivalentTo(records));
        }
コード例 #26
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestSOAMinTTLIsEnforced()
        {
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""7200"" 
         primary-ns=""ns.example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />

    <A name=""www.example.com"" class=""IN"" ttl=""5"" address=""192.168.0.1"" />
</zone>
			"            );

            var zone = DNSZone.Unserialize(config);

            var records = new List <DNSRecord>();

            records.Add(new DNSRecord(
                            new Domain("www.example.com"),
                            AddressClass.INTERNET,
                            60,
                            new AResource(IPv4Address.Parse("192.168.0.1"))));

            Assert.That(zone.Records, Is.EquivalentTo(records));
        }
コード例 #27
0
ファイル: ZoneTest.cs プロジェクト: adamnew123456/DNS
        public void TestConfigPTRRecordV6()
        {
            var config = ParseXML(@"
<zone>
	<SOA name=""example.com"" class=""IN"" ttl=""7200"" 
         primary-ns=""ns.example.com"" hostmaster=""admin.example.com""
         serial=""0"" refresh=""3600"" retry=""60"" expire=""3600"" min-ttl=""60"" />

    <PTR name=""b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa"" class=""IN"" ttl=""3600"" pointer=""www.example.com"" />
</zone>
			"            );

            var zone = DNSZone.Unserialize(config);

            var records = new List <DNSRecord>();

            records.Add(new DNSRecord(
                            new Domain("b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa"),
                            AddressClass.INTERNET,
                            3600,
                            new PTRResource(new Domain("www.example.com"))));

            Assert.That(zone.Records, Is.EquivalentTo(records));
        }
コード例 #28
0
ファイル: Zone.cs プロジェクト: adamnew123456/DNS
        /**
         * Produces a new zone from an input XML file.
         */
        public static DNSZone Unserialize(XmlDocument config)
        {
            DNSRecord start_of_authority = null;
            var       records            = new List <DNSRecord>();
            var       relays             = new List <EndPoint>();

            if (config.DocumentElement.Name != "zone")
            {
                throw new InvalidDataException("Root element must be called zone");
            }

            foreach (var entry in config.DocumentElement.ChildNodes.OfType <XmlNode>())
            {
                if (entry.NodeType != XmlNodeType.Element)
                {
                    logger.Trace("Ignoring node of type {0}", entry.NodeType);
                    continue;
                }

                bool is_record =
                    entry.Name == "A" ||
                    entry.Name == "NS" ||
                    entry.Name == "CNAME" ||
                    entry.Name == "MX" ||
                    entry.Name == "SOA" ||
                    entry.Name == "PTR" ||
                    entry.Name == "AAAA";

                if (is_record)
                {
                    if (entry.Attributes["name"] == null ||
                        entry.Attributes["class"] == null ||
                        entry.Attributes["ttl"] == null)
                    {
                        throw new InvalidDataException("Resource records must have 'name', 'class' and 'ttl' attributes");
                    }

                    var record_name = new Domain(entry.Attributes["name"].Value);

                    AddressClass record_class;
                    switch (entry.Attributes["class"].Value)
                    {
                    case "IN":
                        record_class = AddressClass.INTERNET;
                        break;

                    default:
                        throw new InvalidDataException("Only address class 'IN' is supported");
                    }

                    UInt32 record_ttl = 0;
                    try
                    {
                        record_ttl = UInt32.Parse(entry.Attributes["ttl"].Value);
                    }
                    catch (Exception err)
                    {
                        if (err is OverflowException || err is FormatException)
                        {
                            throw new InvalidDataException(entry.Attributes["ttl"].Value + " is not a valid TTL");
                        }
                        else
                        {
                            throw;
                        }
                    }

                    IDNSResource resource = null;
                    switch (entry.Name)
                    {
                    case "A":
                        if (entry.Attributes["address"] == null)
                        {
                            throw new InvalidDataException("A record must have address");
                        }


                        IPv4Address address;
                        try
                        {
                            address = IPv4Address.Parse(entry.Attributes["address"].Value);
                        }
                        catch (FormatException)
                        {
                            throw new InvalidDataException(entry.Attributes["address"].Value + " is not a valid IPv4 address");
                        }

                        resource = new AResource(address);
                        logger.Trace("A record: address={0}", ((AResource)resource).Address);
                        break;

                    case "NS":
                        if (entry.Attributes["nameserver"] == null)
                        {
                            throw new InvalidDataException("NS record must have a nameserver");
                        }

                        resource = new NSResource(new Domain(entry.Attributes["nameserver"].Value));
                        logger.Trace("NS record: nameserver={0}", ((NSResource)resource).Nameserver);
                        break;

                    case "CNAME":
                        if (entry.Attributes["alias"] == null)
                        {
                            throw new InvalidDataException("CNAME record must have an alias");
                        }

                        resource = new CNAMEResource(new Domain(entry.Attributes["alias"].Value));
                        logger.Trace("CNAME record: alias={0}", ((CNAMEResource)resource).Alias);
                        break;

                    case "MX":
                        if (entry.Attributes["priority"] == null ||
                            entry.Attributes["mailserver"] == null)
                        {
                            throw new InvalidDataException("MX record must have priority and mailserver");
                        }

                        var mailserver = new Domain(entry.Attributes["mailserver"].Value);

                        UInt16 preference = 0;
                        try
                        {
                            preference = UInt16.Parse(entry.Attributes["priority"].Value);
                        }
                        catch (Exception err)
                        {
                            if (err is OverflowException || err is FormatException)
                            {
                                throw new InvalidDataException(entry.Attributes["priority"].Value + " is not a valid priority value");
                            }
                            else
                            {
                                throw;
                            }
                        }

                        resource = new MXResource(preference, mailserver);

                        logger.Trace("MX record: priority={0} mailserver={1}",
                                     ((MXResource)resource).Preference,
                                     ((MXResource)resource).Mailserver);
                        break;

                    case "PTR":
                        if (entry.Attributes["pointer"] == null)
                        {
                            throw new InvalidDataException("PTR record must have pointer");
                        }

                        if (!reverse_zone_v4.IsSubdomain(record_name) && !reverse_zone_v6.IsSubdomain(record_name))
                        {
                            throw new InvalidDataException("PTR record be in the in-addr.arpa or ip6.arpa zone");
                        }

                        resource = new PTRResource(new Domain(entry.Attributes["pointer"].Value));
                        logger.Trace("PTR record: pointer={0}", ((PTRResource)resource).Pointer);
                        break;

                    case "AAAA":
                        if (entry.Attributes["address"] == null)
                        {
                            throw new InvalidDataException("AAAA record must have address");
                        }


                        IPv6Address v6address;
                        try
                        {
                            v6address = IPv6Address.Parse(entry.Attributes["address"].Value);
                        }
                        catch (FormatException)
                        {
                            throw new InvalidDataException(entry.Attributes["address"].Value + " is not a valid IPv4 address");
                        }

                        resource = new AAAAResource(v6address);
                        logger.Trace("AAAA record: address={0}", ((AAAAResource)resource).Address);
                        break;


                    case "SOA":
                        if (entry.Attributes["primary-ns"] == null ||
                            entry.Attributes["hostmaster"] == null ||
                            entry.Attributes["serial"] == null ||
                            entry.Attributes["refresh"] == null ||
                            entry.Attributes["retry"] == null ||
                            entry.Attributes["expire"] == null ||
                            entry.Attributes["min-ttl"] == null)
                        {
                            throw new InvalidDataException("SOA record missing one of: primary-ns, hostmaster, serial, refresh, retry, expire and min-ttl");
                        }

                        var primary_ns = new Domain(entry.Attributes["primary-ns"].Value);
                        var hostmaster = new Domain(entry.Attributes["hostmaster"].Value);

                        UInt32 serial = 0;
                        try
                        {
                            serial = UInt32.Parse(entry.Attributes["serial"].Value);
                        }
                        catch (Exception err)
                        {
                            if (err is OverflowException || err is FormatException)
                            {
                                throw new InvalidDataException(entry.Attributes["serial"].Value + " is not a valid serial number");
                            }
                            else
                            {
                                throw;
                            }
                        }

                        UInt32 refresh = 0;
                        try
                        {
                            refresh = UInt32.Parse(entry.Attributes["refresh"].Value);
                        }
                        catch (Exception err)
                        {
                            if (err is OverflowException || err is FormatException)
                            {
                                throw new InvalidDataException(entry.Attributes["refresh"].Value + " is not a valid refresh value");
                            }
                            else
                            {
                                throw;
                            }
                        }

                        UInt32 retry = 0;
                        try
                        {
                            retry = UInt32.Parse(entry.Attributes["retry"].Value);
                        }
                        catch (Exception err)
                        {
                            if (err is OverflowException || err is FormatException)
                            {
                                throw new InvalidDataException(entry.Attributes["retry"].Value + " is not a valid retry value");
                            }
                            else
                            {
                                throw;
                            }
                        }

                        UInt32 expire = 0;
                        try
                        {
                            expire = UInt32.Parse(entry.Attributes["expire"].Value);
                        }
                        catch (Exception err)
                        {
                            if (err is OverflowException || err is FormatException)
                            {
                                throw new InvalidDataException(entry.Attributes["expire"].Value + " is not a valid expire value");
                            }
                            else
                            {
                                throw;
                            }
                        }

                        UInt32 minttl = 0;
                        try
                        {
                            minttl = UInt32.Parse(entry.Attributes["min-ttl"].Value);
                        }
                        catch (Exception err)
                        {
                            if (err is OverflowException || err is FormatException)
                            {
                                throw new InvalidDataException(entry.Attributes["min-ttl"].Value + " is not a valid expire value");
                            }
                            else
                            {
                                throw;
                            }
                        }

                        resource = new SOAResource(primary_ns, hostmaster, serial, refresh, retry, expire, minttl);

                        logger.Trace("SOA record: primary-ns={0} hostmaster={1} serial={2} refresh={3} retry={4} expire={5} min-ttl={6}",
                                     ((SOAResource)resource).PrimaryNameServer,
                                     ((SOAResource)resource).Hostmaster,
                                     ((SOAResource)resource).Serial,
                                     ((SOAResource)resource).RefreshSeconds,
                                     ((SOAResource)resource).RetrySeconds,
                                     ((SOAResource)resource).ExpireSeconds,
                                     ((SOAResource)resource).MinimumTTL);

                        break;
                    }

                    var record = new DNSRecord(record_name, record_class, record_ttl, resource);
                    if (record.Resource.Type == ResourceRecordType.START_OF_AUTHORITY)
                    {
                        if (start_of_authority == null)
                        {
                            logger.Trace("Found SOA: {0}", record);
                            start_of_authority = record;
                        }
                        else
                        {
                            throw new InvalidDataException("Cannot have more than one SOA record in zone");
                        }
                    }
                    else
                    {
                        logger.Trace("Found other record: {0}", record);
                        records.Add(record);
                    }
                }
                else if (entry.Name == "relay")
                {
                    if (entry.Attributes["address"] == null ||
                        entry.Attributes["port"] == null)
                    {
                        throw new InvalidDataException("relay record must have address and port");
                    }

                    IPAddress address;
                    int       port;

                    try
                    {
                        address = IPAddress.Parse(entry.Attributes["address"].Value);
                    }
                    catch (FormatException)
                    {
                        throw new InvalidDataException(entry.Attributes["address"].Value + " is not a valid IPv4 address");
                    }

                    try
                    {
                        port = int.Parse(entry.Attributes["port"].Value);
                    }
                    catch (FormatException)
                    {
                        throw new InvalidDataException(entry.Attributes["port"].Value + " is not a valid port");
                    }

                    try
                    {
                        relays.Add(new IPEndPoint(address, port));
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        throw new InvalidDataException(entry.Attributes["port"].Value + " is not a valid port");
                    }

                    logger.Trace("Found relay: {0}:{1}", address, port);
                }
                else
                {
                    throw new InvalidDataException(entry.Name + " is not a valid zone entry");
                }
            }

            if (start_of_authority == null)
            {
                throw new InvalidDataException("Zone does not have SOA record");
            }

            var zone = new DNSZone(start_of_authority, relays.ToArray());

            foreach (var record in records)
            {
                if (record.TimeToLive < ((SOAResource)start_of_authority.Resource).MinimumTTL)
                {
                    logger.Trace("Correcting TTL: Record {0} has smaller TTL than SOA MinTTL {1}",
                                 record, start_of_authority);
                    record.TimeToLive = ((SOAResource)start_of_authority.Resource).MinimumTTL;
                }

                zone.Add(record);
            }

            return(zone);
        }
コード例 #29
0
 public QueryExecutor(DNSZone zone, IResolver resolver, IDNSCache cache)
 {
     this.zone     = zone;
     this.resolver = resolver;
     this.cache    = cache;
 }