public DnsDatagram(dynamic jsonResponse) { _header = new DnsHeader(jsonResponse); { _question = new DnsQuestionRecord[_header.QDCOUNT]; int i = 0; foreach (dynamic jsonQuestionRecord in jsonResponse.Question) { _question[i++] = new DnsQuestionRecord(jsonQuestionRecord); } } if (jsonResponse.Answer == null) { _answer = new DnsResourceRecord[] { }; } else { _answer = new DnsResourceRecord[_header.ANCOUNT]; int i = 0; foreach (dynamic jsonAnswerRecord in jsonResponse.Answer) { _answer[i++] = new DnsResourceRecord(jsonAnswerRecord); } } if (jsonResponse.Authority == null) { _authority = new DnsResourceRecord[] { }; } else { _authority = new DnsResourceRecord[_header.NSCOUNT]; int i = 0; foreach (dynamic jsonAuthorityRecord in jsonResponse.Authority) { _authority[i++] = new DnsResourceRecord(jsonAuthorityRecord); } } if (jsonResponse.Additional == null) { _additional = new DnsResourceRecord[] { }; } else { _additional = new DnsResourceRecord[_header.ARCOUNT]; int i = 0; foreach (dynamic jsonAdditionalRecord in jsonResponse.Additional) { _additional[i++] = new DnsResourceRecord(jsonAdditionalRecord); } } }
internal DnsDatagram CloneRequest() { DnsQuestionRecord[] clonedQuestion = new DnsQuestionRecord[_question.Count]; for (int i = 0; i < _question.Count; i++) { clonedQuestion[i] = _question[i].Clone(); } return(new DnsDatagram(_ID, _QR == 1, _OPCODE, _AA == 1, _TC == 1, _RD == 1, _RA == 1, _AD == 1, _CD == 1, _RCODE, clonedQuestion, _answer, _authority, _additional)); }
private DnsDatagram QueryCache(DnsHeader header, DnsQuestionRecord question) { string domain = question.Name.ToLower(); DnsResourceRecord[] records = GetRecords(domain, question.Type); if (records != null) { if (records[0].RDATA is DnsEmptyRecord) { return(new DnsDatagram(new DnsHeader(header.Identifier, true, DnsOpcode.StandardQuery, false, false, header.RecursionDesired, true, false, false, DnsResponseCode.NoError, 1, 0, 1, 0), new DnsQuestionRecord[] { question }, new DnsResourceRecord[] { }, new DnsResourceRecord[] { (records[0].RDATA as DnsEmptyRecord).Authority }, new DnsResourceRecord[] { })); } if (records[0].RDATA is DnsNXRecord) { return(new DnsDatagram(new DnsHeader(header.Identifier, true, DnsOpcode.StandardQuery, false, false, header.RecursionDesired, true, false, false, DnsResponseCode.NameError, 1, 0, 1, 0), new DnsQuestionRecord[] { question }, new DnsResourceRecord[] { }, new DnsResourceRecord[] { (records[0].RDATA as DnsNXRecord).Authority }, new DnsResourceRecord[] { })); } return(new DnsDatagram(new DnsHeader(header.Identifier, true, DnsOpcode.StandardQuery, false, false, header.RecursionDesired, true, false, false, DnsResponseCode.NoError, 1, (ushort)records.Length, 0, 0), new DnsQuestionRecord[] { question }, records, new DnsResourceRecord[] { }, new DnsResourceRecord[] { })); } DnsResourceRecord[] nameServers = GetNearestNameServers(domain); if (nameServers != null) { List <DnsResourceRecord> glueRecords = new List <DnsResourceRecord>(); foreach (DnsResourceRecord nameServer in nameServers) { string nsDomain = (nameServer.RDATA as DnsNSRecord).NSDomainName; DnsResourceRecord[] glueAs = GetRecords(nsDomain, DnsResourceRecordType.A); if (glueAs != null) { glueRecords.AddRange(glueAs); } DnsResourceRecord[] glueAAAAs = GetRecords(nsDomain, DnsResourceRecordType.AAAA); if (glueAAAAs != null) { glueRecords.AddRange(glueAAAAs); } } DnsResourceRecord[] additional = glueRecords.ToArray(); return(new DnsDatagram(new DnsHeader(header.Identifier, true, DnsOpcode.StandardQuery, false, false, header.RecursionDesired, true, false, false, DnsResponseCode.NoError, 1, 0, (ushort)nameServers.Length, (ushort)additional.Length), new DnsQuestionRecord[] { question }, new DnsResourceRecord[] { }, nameServers, additional)); } return(null); }
public static DnsDatagram ResolveViaNameServers(string domain, DnsResourceRecordType queryType, NameServerAddress[] nameServers = null, IDnsCache cache = null, NetProxy proxy = null, bool preferIPv6 = false, bool tcp = false, int retries = 2, int maxStackCount = 10) { DnsQuestionRecord question; if (queryType == DnsResourceRecordType.PTR) { question = new DnsQuestionRecord(IPAddress.Parse(domain), DnsClass.IN); } else { question = new DnsQuestionRecord(domain, queryType, DnsClass.IN); } return(ResolveViaNameServers(question, nameServers, cache, proxy, preferIPv6, tcp, retries, maxStackCount)); }
internal DnsDatagram CloneHeadersAndQuestions() { DnsQuestionRecord[] clonedQuestion = new DnsQuestionRecord[_question.Count]; for (int i = 0; i < _question.Count; i++) { clonedQuestion[i] = _question[i].Clone(); } DnsDatagram datagram = new DnsDatagram(_ID, _QR == 1, _OPCODE, _AA == 1, _TC == 1, _RD == 1, _RA == 1, _AD == 1, _CD == 1, _RCODE, clonedQuestion, _answer, _authority, _additional); datagram._metadata = _metadata; return(datagram); }
public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return(false); } if (ReferenceEquals(this, obj)) { return(true); } DnsQuestionRecord other = obj as DnsQuestionRecord; if (other == null) { return(false); } if (!_name.Equals(other._name, StringComparison.OrdinalIgnoreCase)) { return(false); } if (_type != other._type) { return(false); } if (_class != other._class) { return(false); } return(true); }
public DnsDatagram Resolve(DnsQuestionRecord questionRecord) { return(Resolve(new DnsDatagram(new DnsHeader(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, 1, 0, 0, 0), new DnsQuestionRecord[] { questionRecord }, null, null, null))); }
public static DnsDatagram ResolveViaNameServers(DnsQuestionRecord question, NameServerAddress[] nameServers = null, IDnsCache cache = null, NetProxy proxy = null, bool preferIPv6 = false, bool tcp = false, int retries = 2, int maxStackCount = 10) { if ((nameServers != null) && (nameServers.Length > 0)) { //create copy of name servers array so that the values in original array are not messed due to shuffling feature NameServerAddress[] nameServersCopy = new NameServerAddress[nameServers.Length]; Array.Copy(nameServers, nameServersCopy, nameServers.Length); nameServers = nameServersCopy; } Stack <ResolverData> resolverStack = new Stack <ResolverData>(); int stackNameServerIndex = 0; while (true) //stack loop { if (resolverStack.Count > maxStackCount) { while (resolverStack.Count > 0) { ResolverData data = resolverStack.Pop(); question = data.Question; } throw new DnsClientException("DnsClient exceeded the maximum stack count to resolve the domain: " + question.Name); } if (cache != null) { DnsDatagram request = new DnsDatagram(new DnsHeader(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, 1, 0, 0, 0), new DnsQuestionRecord[] { question }, null, null, null); DnsDatagram cacheResponse = cache.Query(request); switch (cacheResponse.Header.RCODE) { case DnsResponseCode.NoError: if (cacheResponse.Answer.Length > 0) { if (resolverStack.Count == 0) { return(cacheResponse); } else { ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex; switch (cacheResponse.Answer[0].Type) { case DnsResourceRecordType.AAAA: nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (cacheResponse.Answer[0].RDATA as DnsAAAARecord).Address); break; case DnsResourceRecordType.A: nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (cacheResponse.Answer[0].RDATA as DnsARecord).Address); break; default: //didnt find IP for current name server stackNameServerIndex++; //increment to skip current name server break; } continue; //stack loop } } if (cacheResponse.Authority.Length > 0) { if (cacheResponse.Authority[0].Type == DnsResourceRecordType.SOA) { if (resolverStack.Count == 0) { return(cacheResponse); } else { if (question.Type == DnsResourceRecordType.AAAA) { question = new DnsQuestionRecord(question.Name, DnsResourceRecordType.A, question.Class); } else { //didnt find IP for current name server //pop and try next name server ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server } continue; //to stack loop } } if ((nameServers == null) || (nameServers.Length == 0)) { NameServerAddress[] cacheNameServers = NameServerAddress.GetNameServersFromResponse(cacheResponse, preferIPv6, true); if (cacheNameServers.Length > 0) { nameServers = cacheNameServers; } } } break; case DnsResponseCode.NameError: if (resolverStack.Count == 0) { return(cacheResponse); } else { //current name server domain doesnt exists //pop and try next name server ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server continue; //stack loop } } } if ((nameServers == null) || (nameServers.Length == 0)) { //create copy of root name servers array so that the values in original array are not messed due to shuffling feature if (preferIPv6) { nameServers = new NameServerAddress[ROOT_NAME_SERVERS_IPv6.Length]; Array.Copy(ROOT_NAME_SERVERS_IPv6, nameServers, ROOT_NAME_SERVERS_IPv6.Length); } else { nameServers = new NameServerAddress[ROOT_NAME_SERVERS_IPv4.Length]; Array.Copy(ROOT_NAME_SERVERS_IPv4, nameServers, ROOT_NAME_SERVERS_IPv4.Length); } } NameServerAddress.Shuffle(nameServers); int hopCount = 0; while ((hopCount++) < MAX_HOPS) //resolver loop { //copy and reset stack name server index since its one time use only after stack pop int i = stackNameServerIndex; stackNameServerIndex = 0; //query name servers one by one for (; i < nameServers.Length; i++) //retry next server loop { NameServerAddress currentNameServer = nameServers[i]; if (question.Name == currentNameServer.Domain) { continue; //obvious! } if (currentNameServer.EndPoint == null) { resolverStack.Push(new ResolverData(question, nameServers, i)); if (preferIPv6) { question = new DnsQuestionRecord(currentNameServer.Domain, DnsResourceRecordType.AAAA, question.Class); } else { question = new DnsQuestionRecord(currentNameServer.Domain, DnsResourceRecordType.A, question.Class); } nameServers = null; goto stackLoop; } DnsClient client = new DnsClient(currentNameServer); client._proxy = proxy; client._preferIPv6 = preferIPv6; client._tcp = tcp; client._retries = retries; DnsDatagram request = new DnsDatagram(new DnsHeader(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, 1, 0, 0, 0), new DnsQuestionRecord[] { question }, null, null, null); DnsDatagram response; try { response = client.Resolve(request); } catch (DnsClientException) { continue; //resolver loop } if (response.Header.Truncation) { if (tcp) { return(response); } client._tcp = true; response = client.Resolve(request); } if (cache != null) { cache.CacheResponse(response); } switch (response.Header.RCODE) { case DnsResponseCode.NoError: if (response.Answer.Length > 0) { if (!response.Answer[0].Name.Equals(question.Name, StringComparison.CurrentCultureIgnoreCase)) { continue; //continue to next name server since current name server may be misconfigured } if (resolverStack.Count == 0) { return(response); } else { ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex; switch (response.Answer[0].Type) { case DnsResourceRecordType.AAAA: nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (response.Answer[0].RDATA as DnsAAAARecord).Address); break; case DnsResourceRecordType.A: nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (response.Answer[0].RDATA as DnsARecord).Address); break; default: //didnt find IP for current name server stackNameServerIndex++; //increment to skip current name server break; } goto resolverLoop; } } if (response.Authority.Length == 0) { continue; //continue to next name server since current name server may be misconfigured } if (response.Authority[0].Type == DnsResourceRecordType.SOA) { //no entry for given type if (resolverStack.Count == 0) { return(response); } else { if (question.Type == DnsResourceRecordType.AAAA) { question = new DnsQuestionRecord(question.Name, DnsResourceRecordType.A, question.Class); } else { //didnt find IP for current name server //pop and try next name server ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server } goto stackLoop; //goto stack loop } } nameServers = NameServerAddress.GetNameServersFromResponse(response, preferIPv6, false); if (nameServers.Length == 0) { continue; //continue to next name server since current name server may be misconfigured } goto resolverLoop; case DnsResponseCode.NameError: if (resolverStack.Count == 0) { return(response); } else { //current name server domain doesnt exists //pop and try next name server ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server goto stackLoop; //goto stack loop } default: continue; //continue to next name server since current name server may be misconfigured } } if (resolverStack.Count == 0) { throw new DnsClientException("DnsClient failed to resolve the request: no response from name servers."); } else { //didnt find IP for current name server //pop and try next name server ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server break; //to stack loop } resolverLoop :; } stackLoop :; } }
public ResolverData(DnsQuestionRecord question, NameServerAddress[] nameServers, int nameServerIndex) { this.Question = question; this.NameServers = nameServers; this.NameServerIndex = nameServerIndex; }
public virtual DnsDatagram Query(DnsDatagram request, bool serveStale = false) { if (serveStale) { throw new NotImplementedException("DnsCache does not implement serve stale."); } DnsQuestionRecord question = request.Question[0]; IReadOnlyList <DnsResourceRecord> answerRecords = GetRecords(question.Name, question.Type); if (answerRecords != null) { if (answerRecords[0].RDATA is DnsEmptyRecord) { DnsResourceRecord[] responseAuthority; DnsResourceRecord authority = (answerRecords[0].RDATA as DnsEmptyRecord).Authority; if (authority == null) { responseAuthority = Array.Empty <DnsResourceRecord>(); } else { responseAuthority = new DnsResourceRecord[] { authority } }; return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, null, responseAuthority)); } if (answerRecords[0].RDATA is DnsNXRecord) { DnsResourceRecord[] responseAuthority; DnsResourceRecord authority = (answerRecords[0].RDATA as DnsNXRecord).Authority; if (authority == null) { responseAuthority = Array.Empty <DnsResourceRecord>(); } else { responseAuthority = new DnsResourceRecord[] { authority } }; return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NameError, request.Question, null, responseAuthority)); } if (answerRecords[0].RDATA is DnsANYRecord) { DnsANYRecord anyRR = answerRecords[0].RDATA as DnsANYRecord; return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, anyRR.Records)); } if (answerRecords[0].RDATA is DnsFailureRecord) { return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, (answerRecords[0].RDATA as DnsFailureRecord).RCODE, request.Question)); } IReadOnlyList <DnsResourceRecord> additionalRecords = null; switch (question.Type) { case DnsResourceRecordType.NS: case DnsResourceRecordType.MX: case DnsResourceRecordType.SRV: additionalRecords = GetAdditionalRecords(answerRecords); break; } return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, answerRecords, null, additionalRecords)); } IReadOnlyList <DnsResourceRecord> closestAuthority = GetClosestNameServers(question.Name); if (closestAuthority != null) { IReadOnlyList <DnsResourceRecord> additionalRecords = GetAdditionalRecords(closestAuthority); return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, null, closestAuthority, additionalRecords)); } return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.Refused, request.Question)); }
public virtual DnsDatagram Query(DnsDatagram request, bool serveStale = false) { if (serveStale) { throw new NotImplementedException("DnsCache does not implement serve stale."); } DnsQuestionRecord question = request.Question[0]; IReadOnlyList <DnsResourceRecord> answerRecords = GetRecords(question.Name, question.Type); if (answerRecords != null) { if (answerRecords[0].RDATA is DnsEmptyRecord) { DnsResourceRecord[] responseAuthority; DnsResourceRecord authority = (answerRecords[0].RDATA as DnsEmptyRecord).Authority; if (authority == null) { responseAuthority = Array.Empty <DnsResourceRecord>(); } else { responseAuthority = new DnsResourceRecord[] { authority } }; return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, null, responseAuthority)); } if (answerRecords[0].RDATA is DnsNXRecord) { DnsResourceRecord[] responseAuthority; DnsResourceRecord authority = (answerRecords[0].RDATA as DnsNXRecord).Authority; if (authority == null) { responseAuthority = Array.Empty <DnsResourceRecord>(); } else { responseAuthority = new DnsResourceRecord[] { authority } }; return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NameError, request.Question, null, responseAuthority)); } if (answerRecords[0].RDATA is DnsANYRecord) { DnsANYRecord anyRR = answerRecords[0].RDATA as DnsANYRecord; return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, anyRR.Records)); } if (answerRecords[0].RDATA is DnsFailureRecord) { return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, (answerRecords[0].RDATA as DnsFailureRecord).RCODE, request.Question)); } return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, answerRecords)); } string currentZone = question.Name; while (currentZone != null) { IReadOnlyList <DnsResourceRecord> nameServers = GetClosestNameServers(currentZone); if (nameServers == null) { break; } List <DnsResourceRecord> glueRecords = new List <DnsResourceRecord>(); foreach (DnsResourceRecord nameServer in nameServers) { string nsDomain = (nameServer.RDATA as DnsNSRecord).NameServer; IReadOnlyList <DnsResourceRecord> glueAs = GetRecords(nsDomain, DnsResourceRecordType.A); if ((glueAs != null) && (glueAs.Count > 0) && (glueAs[0].RDATA is DnsARecord)) { glueRecords.AddRange(glueAs); } IReadOnlyList <DnsResourceRecord> glueAAAAs = GetRecords(nsDomain, DnsResourceRecordType.AAAA); if ((glueAAAAs != null) && (glueAAAAs.Count > 0) && (glueAAAAs[0].RDATA is DnsAAAARecord)) { glueRecords.AddRange(glueAAAAs); } } if (glueRecords.Count > 0) { return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, null, nameServers, glueRecords)); } currentZone = GetParentZone(currentZone); } return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.Refused, request.Question)); }
public override DnsDatagram Query(DnsDatagram request) { DnsQuestionRecord question = request.Question[0]; DnsResourceRecord[] answerRecords = GetRecords(question.Name, question.Type); if (answerRecords != null) { if (answerRecords[0].RDATA is DnsEmptyRecord) { DnsResourceRecord[] responseAuthority; DnsResourceRecord authority = (answerRecords[0].RDATA as DnsEmptyRecord).Authority; if (authority == null) { responseAuthority = new DnsResourceRecord[] { } } ; else { responseAuthority = new DnsResourceRecord[] { authority } }; return(new DnsDatagram(new DnsHeader(request.Header.Identifier, true, DnsOpcode.StandardQuery, false, false, request.Header.RecursionDesired, true, false, false, DnsResponseCode.NoError, 1, 0, 1, 0), request.Question, new DnsResourceRecord[] { }, responseAuthority, new DnsResourceRecord[] { })); } if (answerRecords[0].RDATA is DnsNXRecord) { DnsResourceRecord[] responseAuthority; DnsResourceRecord authority = (answerRecords[0].RDATA as DnsNXRecord).Authority; if (authority == null) { responseAuthority = new DnsResourceRecord[] { } } ; else { responseAuthority = new DnsResourceRecord[] { authority } }; return(new DnsDatagram(new DnsHeader(request.Header.Identifier, true, DnsOpcode.StandardQuery, false, false, request.Header.RecursionDesired, true, false, false, DnsResponseCode.NameError, 1, 0, 1, 0), request.Question, new DnsResourceRecord[] { }, responseAuthority, new DnsResourceRecord[] { })); } if (answerRecords[0].RDATA is DnsANYRecord) { DnsANYRecord anyRR = answerRecords[0].RDATA as DnsANYRecord; return(new DnsDatagram(new DnsHeader(request.Header.Identifier, true, DnsOpcode.StandardQuery, false, false, request.Header.RecursionDesired, true, false, false, DnsResponseCode.NoError, 1, (ushort)anyRR.Records.Length, 0, 0), request.Question, anyRR.Records, new DnsResourceRecord[] { }, new DnsResourceRecord[] { })); } if (answerRecords[0].RDATA is DnsFailureRecord) { return(new DnsDatagram(new DnsHeader(request.Header.Identifier, true, DnsOpcode.StandardQuery, false, false, request.Header.RecursionDesired, true, false, false, (answerRecords[0].RDATA as DnsFailureRecord).RCODE, 1, 0, 0, 0), request.Question, new DnsResourceRecord[] { }, new DnsResourceRecord[] { }, new DnsResourceRecord[] { })); } return(new DnsDatagram(new DnsHeader(request.Header.Identifier, true, DnsOpcode.StandardQuery, false, false, request.Header.RecursionDesired, true, false, false, DnsResponseCode.NoError, 1, (ushort)answerRecords.Length, 0, 0), request.Question, answerRecords, new DnsResourceRecord[] { }, new DnsResourceRecord[] { })); } string currentZone = question.Name; while (currentZone != null) { DnsResourceRecord[] nameServers = GetClosestNameServers(currentZone); if (nameServers == null) { break; } List <DnsResourceRecord> glueRecords = new List <DnsResourceRecord>(); foreach (DnsResourceRecord nameServer in nameServers) { string nsDomain = (nameServer.RDATA as DnsNSRecord).NSDomainName; DnsResourceRecord[] glueAs = GetRecords(nsDomain, DnsResourceRecordType.A); if ((glueAs != null) && (glueAs.Length > 0) && (glueAs[0].RDATA is DnsARecord)) { glueRecords.AddRange(glueAs); } DnsResourceRecord[] glueAAAAs = GetRecords(nsDomain, DnsResourceRecordType.AAAA); if ((glueAAAAs != null) && (glueAAAAs.Length > 0) && (glueAAAAs[0].RDATA is DnsAAAARecord)) { glueRecords.AddRange(glueAAAAs); } } if (glueRecords.Count > 0) { DnsResourceRecord[] additional = glueRecords.ToArray(); return(new DnsDatagram(new DnsHeader(request.Header.Identifier, true, DnsOpcode.StandardQuery, false, false, request.Header.RecursionDesired, true, false, false, DnsResponseCode.NoError, 1, 0, (ushort)nameServers.Length, (ushort)additional.Length), request.Question, new DnsResourceRecord[] { }, nameServers, additional)); } currentZone = GetParentZone(currentZone); } return(new DnsDatagram(new DnsHeader(request.Header.Identifier, true, DnsOpcode.StandardQuery, false, false, request.Header.RecursionDesired, true, false, false, DnsResponseCode.Refused, 1, 0, 0, 0), request.Question, new DnsResourceRecord[] { }, new DnsResourceRecord[] { }, new DnsResourceRecord[] { })); }