ReadOnlyCollection<DnsQuestion> GetQuestions (int count) { if (count <= 0) return EmptyQS; List<DnsQuestion> records = new List<DnsQuestion> (count); for(int i = 0; i < count; i++) { DnsQuestion record = new DnsQuestion (); offset = record.Init (this, offset); records.Add (record); } return records.AsReadOnly (); }
void ProcessResponse(SimpleResolverEventArgs args, DnsResponse response, EndPoint server_ep) { DnsRCode status = response.Header.RCode; if (status != 0) { if (args.PTRAddress != null) { // PTR query failed -> no error, we have the IP return; } args.ResolverError = (ResolverError)status; return; } // TODO: verify IP of the server is in our list and the same one that got the query IPEndPoint ep = (IPEndPoint)server_ep; if (ep.Port != 53) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "Port"; return; } DnsHeader header = response.Header; if (!header.IsQuery) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "IsQuery"; return; } // TODO: handle Truncation. Retry with bigger buffer? if (header.QuestionCount > 1) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "QuestionCount"; return; } ReadOnlyCollection <DnsQuestion> q = response.GetQuestions(); if (q.Count != 1) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "QuestionCount 2"; return; } DnsQuestion question = q [0]; /* The answer might have dot at the end, etc... * if (String.Compare (question.Name, args.HostName) != 0) { * args.ResolverError = ResolverError.ResponseHeaderError; * args.ErrorMessage = "HostName - " + question.Name + " != " + args.HostName; * return; * } */ DnsQType t = question.Type; if (t != DnsQType.A && t != DnsQType.AAAA && t != DnsQType.PTR) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "QType " + question.Type; return; } if (question.Class != DnsQClass.IN) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "QClass " + question.Class; return; } ReadOnlyCollection <DnsResourceRecord> records = response.GetAnswers(); if (records.Count == 0) { if (args.PTRAddress != null) { // PTR query failed -> no error return; } args.ResolverError = ResolverError.NameError; // is this ok? args.ErrorMessage = "NoAnswers"; return; } List <string> aliases = null; List <IPAddress> addresses = null; foreach (DnsResourceRecord r in records) { if (r.Class != DnsClass.IN) { continue; } if (r.Type == DnsType.A || r.Type == DnsType.AAAA) { if (addresses == null) { addresses = new List <IPAddress> (); } addresses.Add(((DnsResourceRecordIPAddress)r).Address); } else if (r.Type == DnsType.CNAME) { if (aliases == null) { aliases = new List <string> (); } aliases.Add(((DnsResourceRecordCName)r).CName); } else if (r.Type == DnsType.PTR) { args.HostEntry.HostName = ((DnsResourceRecordPTR)r).DName; args.HostEntry.Aliases = aliases == null ? EmptyStrings : aliases.ToArray(); args.HostEntry.AddressList = EmptyAddresses; return; } } IPHostEntry entry = args.HostEntry ?? new IPHostEntry(); if (entry.HostName == null && aliases != null && aliases.Count > 0) { entry.HostName = aliases [0]; aliases.RemoveAt(0); } entry.Aliases = aliases == null ? EmptyStrings : aliases.ToArray(); entry.AddressList = addresses == null ? EmptyAddresses : addresses.ToArray(); args.HostEntry = entry; if ((question.Type == DnsQType.A || question.Type == DnsQType.AAAA) && entry.AddressList == EmptyAddresses) { args.ResolverError = ResolverError.NameError; args.ErrorMessage = "No addresses in response"; } else if (question.Type == DnsQType.PTR && entry.HostName == null) { args.ResolverError = ResolverError.NameError; args.ErrorMessage = "No PTR in response"; } }