예제 #1
0
        public override void SetRecords(DnsResourceRecordType type, IReadOnlyList <DnsResourceRecord> records)
        {
            switch (type)
            {
            case DnsResourceRecordType.SOA:
                if ((records.Count != 1) || !records[0].Name.Equals(_name, StringComparison.OrdinalIgnoreCase))
                {
                    throw new InvalidOperationException("Invalid SOA record.");
                }

                DnsResourceRecord existingSoaRecord = _entries[DnsResourceRecordType.SOA][0];
                DnsResourceRecord newSoaRecord      = records[0];

                existingSoaRecord.CopyRecordInfoFrom(newSoaRecord);
                break;

            default:
                throw new InvalidOperationException("Cannot set records in stub zone.");
            }
        }
예제 #2
0
        private async Task <bool> RefreshZoneAsync(IReadOnlyList <NameServerAddress> nameServers)
        {
            try
            {
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server has started zone refresh for stub zone: " + (_name == "" ? "<root>" : _name));
                    }
                }

                DnsClient client = new DnsClient(nameServers);

                client.Proxy       = _dnsServer.Proxy;
                client.PreferIPv6  = _dnsServer.PreferIPv6;
                client.Timeout     = REFRESH_TIMEOUT;
                client.Retries     = REFRESH_RETRIES;
                client.Concurrency = 1;

                DnsDatagram soaRequest  = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN) }, null, null, null, DnsDatagram.EDNS_DEFAULT_UDP_PAYLOAD_SIZE);
                DnsDatagram soaResponse = await client.ResolveAsync(soaRequest);

                if (soaResponse.RCODE != DnsResponseCode.NoError)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received RCODE=" + soaResponse.RCODE.ToString() + " for '" + (_name == "" ? "<root>" : _name) + "' stub zone refresh from: " + soaResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                if ((soaResponse.Answer.Count < 1) || (soaResponse.Answer[0].Type != DnsResourceRecordType.SOA) || !_name.Equals(soaResponse.Answer[0].Name, StringComparison.OrdinalIgnoreCase))
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received an empty response for SOA query for '" + (_name == "" ? "<root>" : _name) + "' stub zone refresh from: " + soaResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                DnsResourceRecord currentSoaRecord  = _entries[DnsResourceRecordType.SOA][0];
                DnsResourceRecord receivedSoaRecord = soaResponse.Answer[0];

                DnsSOARecordData currentSoa  = currentSoaRecord.RDATA as DnsSOARecordData;
                DnsSOARecordData receivedSoa = receivedSoaRecord.RDATA as DnsSOARecordData;

                //compare using sequence space arithmetic
                if (!_resync && !currentSoa.IsZoneUpdateAvailable(receivedSoa))
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server successfully checked for '" + (_name == "" ? "<root>" : _name) + "' stub zone update from: " + soaResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(true);
                }

                //update available; do zone sync with TCP transport
                List <NameServerAddress> tcpNameServers = new List <NameServerAddress>();

                foreach (NameServerAddress nameServer in nameServers)
                {
                    tcpNameServers.Add(nameServer.ChangeProtocol(DnsTransportProtocol.Tcp));
                }

                nameServers = tcpNameServers;
                client      = new DnsClient(nameServers);

                client.Proxy       = _dnsServer.Proxy;
                client.PreferIPv6  = _dnsServer.PreferIPv6;
                client.Timeout     = REFRESH_TIMEOUT;
                client.Retries     = REFRESH_RETRIES;
                client.Concurrency = 1;

                DnsDatagram nsRequest  = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(_name, DnsResourceRecordType.NS, DnsClass.IN) });
                DnsDatagram nsResponse = await client.ResolveAsync(nsRequest);

                if (nsResponse.RCODE != DnsResponseCode.NoError)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received RCODE=" + nsResponse.RCODE.ToString() + " for '" + (_name == "" ? "<root>" : _name) + "' stub zone refresh from: " + nsResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                if (nsResponse.Answer.Count < 1)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received an empty response for NS query for '" + (_name == "" ? "<root>" : _name) + "' stub zone from: " + nsResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                //prepare sync records
                List <DnsResourceRecord> nsRecords = new List <DnsResourceRecord>(nsResponse.Answer.Count);

                foreach (DnsResourceRecord record in nsResponse.Answer)
                {
                    if ((record.Type == DnsResourceRecordType.NS) && record.Name.Equals(_name, StringComparison.OrdinalIgnoreCase))
                    {
                        record.SyncGlueRecords(nsResponse.Additional);
                        nsRecords.Add(record);
                    }
                }

                receivedSoaRecord.CopyRecordInfoFrom(currentSoaRecord);

                //sync records
                _entries[DnsResourceRecordType.NS]  = nsRecords;
                _entries[DnsResourceRecordType.SOA] = new DnsResourceRecord[] { receivedSoaRecord };

                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server successfully refreshed '" + (_name == "" ? "<root>" : _name) + "' stub zone from: " + nsResponse.Metadata.NameServerAddress.ToString());
                    }
                }

                return(true);
            }
            catch (Exception ex)
            {
                LogManager log = _dnsServer.LogManager;
                if (log != null)
                {
                    string strNameServers = null;

                    foreach (NameServerAddress nameServer in nameServers)
                    {
                        if (strNameServers == null)
                        {
                            strNameServers = nameServer.ToString();
                        }
                        else
                        {
                            strNameServers += ", " + nameServer.ToString();
                        }
                    }

                    log.Write("DNS Server failed to refresh '" + (_name == "" ? "<root>" : _name) + "' stub zone from: " + strNameServers);
                    log.Write(ex);
                }

                return(false);
            }
        }