예제 #1
0
        byte [] GetFreshBuffer()
        {
#if !REUSE_RESPONSES
            return(new byte [512]);
#else
            DnsResponse response = null;
            lock (responses_avail) {
                if (responses_avail.Count > 0)
                {
                    response = responses_avail.Pop();
                }
            }
            if (response == null)
            {
                response = new DnsResponse();
            }
            else
            {
                response.Reset();
            }
            return(response);
#endif
        }
예제 #2
0
		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";
			}

		}
예제 #3
0
		void OnReceive (IAsyncResult ares)
		{
			if (disposed)
				return;

			int nread = 0;
			EndPoint remote_ep = client.RemoteEndPoint;
			try {
				nread = client.EndReceive (ares);
			} catch (Exception e) {
				Console.Error.WriteLine (e);
			}

			BeginReceive ();

			byte [] buffer  = (byte []) ares.AsyncState;
			if (nread > 12) {
				DnsResponse response = new DnsResponse (buffer, nread);
				int id = response.Header.ID;
				SimpleResolverEventArgs args = null;
				lock (queries) {
					if (queries.TryGetValue (id, out args)) {
						queries.Remove (id);
					}
				}

				if (args != null) {
					Timer t = args.Timer;
					if (t != null)
						t.Change (Timeout.Infinite, Timeout.Infinite);

					try {
						ProcessResponse (args, response, remote_ep);
					} catch (Exception e) {
						args.ResolverError = (ResolverError) (-1);
						args.ErrorMessage = e.Message;
					}

					IPHostEntry entry = args.HostEntry;
					if (args.ResolverError != 0 && args.PTRAddress != null && entry != null && entry.HostName != null) {
						args.PTRAddress = null;
						SendAQuery (args, entry.HostName, true);
						args.Timer.Change (5000, Timeout.Infinite);
					} else {
						args.OnCompleted (this);
					}
				}
			}
			FreeBuffer (buffer);
		}
예제 #4
0
		byte [] GetFreshBuffer ()
		{
#if !REUSE_RESPONSES
			return new byte [512];
#else

			DnsResponse response = null;
			lock (responses_avail) {
				if (responses_avail.Count > 0) {
					response = responses_avail.Pop ();
				}
			}
			if (response == null) {
				response = new DnsResponse ();
			} else {
				response.Reset ();
			}
			return response;
#endif
		}
예제 #5
0
        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";
            }
        }
예제 #6
0
        void OnReceive(IAsyncResult ares)
        {
            if (disposed)
            {
                return;
            }

            int      nread     = 0;
            EndPoint remote_ep = client.RemoteEndPoint;

            try {
                nread = client.EndReceive(ares);
            } catch (Exception e) {
                Console.Error.WriteLine(e);
            }

            BeginReceive();

            byte [] buffer = (byte [])ares.AsyncState;
            if (nread > 12)
            {
                DnsResponse             response = new DnsResponse(buffer, nread);
                int                     id       = response.Header.ID;
                SimpleResolverEventArgs args     = null;
                lock (queries) {
                    if (queries.TryGetValue(id, out args))
                    {
                        queries.Remove(id);
                    }
                }

                if (args != null)
                {
                    Timer t = args.Timer;
                    if (t != null)
                    {
                        t.Change(Timeout.Infinite, Timeout.Infinite);
                    }

                    try {
                        ProcessResponse(args, response, remote_ep);
                    } catch (Exception e) {
                        args.ResolverError = (ResolverError)(-1);
                        args.ErrorMessage  = e.Message;
                    }

                    IPHostEntry entry = args.HostEntry;
                    if (args.ResolverError != 0 && args.PTRAddress != null && entry != null && entry.HostName != null)
                    {
                        args.PTRAddress = null;
                        SendAQuery(args, entry.HostName, true);
                        args.Timer.Change(5000, Timeout.Infinite);
                    }
                    else
                    {
                        args.OnCompleted(this);
                    }
                }
            }
            FreeBuffer(buffer);
        }