Esempio n. 1
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);
		}
Esempio n. 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";
			}

		}
Esempio n. 3
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
		}