Пример #1
0
		void GetLocalHost (SimpleResolverEventArgs args)
		{
			//FIXME
			IPHostEntry entry = new IPHostEntry ();
			entry.HostName = "localhost";
			entry.AddressList = new IPAddress [] { IPAddress.Loopback };
			entry.Aliases = EmptyStrings;
			args.ResolverError = 0;
			args.HostEntry = entry;
			return;

/*
			List<IPEndPoint> eps = new List<IPEndPoint> ();
			foreach (NetworkInterface iface in NetworkInterface.GetAllNetworkInterfaces ()) {
				if (NetworkInterfaceType.Loopback == iface.NetworkInterfaceType)
					continue;

				foreach (IPAddress addr in iface.GetIPProperties ().DnsAddresses) {
					if (AddressFamily.InterNetworkV6 == addr.AddressFamily)
						continue;
					IPEndPoint ep = new IPEndPoint (addr, 53);
					if (eps.Contains (ep))
						continue;

					eps.Add (ep);
				}
			}
			endpoints = eps.ToArray ();
*/
		}
Пример #2
0
		static void OnCompleted (object sender, SimpleResolverEventArgs e)
		{
			DnsAsyncResult ares = (DnsAsyncResult) e.UserToken;
			IPHostEntry entry = e.HostEntry;
			if (entry == null || e.ResolverError != 0) {
				ares.SetCompleted (false, new Exception ("Error: " + e.ResolverError));
				return;
			}
			ares.SetCompleted (false, entry);
		}
Пример #3
0
		static IAsyncResult BeginAsyncCall (string host, AsyncCallback callback, object state)
		{
			SimpleResolverEventArgs e = new SimpleResolverEventArgs ();
			e.Completed += OnCompleted;
			e.HostName = host;
			DnsAsyncResult ares = new DnsAsyncResult (callback, state);
			e.UserToken = ares;
			if (resolver.GetHostEntryAsync (e) == false)
				ares.SetCompleted (true, e.HostEntry); // Completed synchronously
			return ares;
		}
Пример #4
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";
			}

		}
Пример #5
0
		void SendPTRQuery (SimpleResolverEventArgs args, bool add_it)
		{
			DnsQuery query = GetQuery (GetPTRName (args.PTRAddress), DnsQType.PTR, DnsQClass.IN);
			SendQuery (args, query, add_it);
		}
Пример #6
0
		void SendQuery (SimpleResolverEventArgs args, DnsQuery query, bool add_it)
		{
			// TODO: not sure about reusing IDs when add_it == false
			int count = 0;
			if (add_it) {
				do {
					query.Header.ID = (ushort)new Random().Next(1, 65534);
					if (count > 500)
						throw new InvalidOperationException ("Too many pending queries (or really bad luck)");
				} while (AddQuery (query, args) == false);
				args.QueryID = query.Header.ID;
			} else {
				query.Header.ID = args.QueryID;
			}
			if (args.Timer == null)
				args.Timer = new Timer (timeout_cb, args, 5000, Timeout.Infinite);
			else
				args.Timer.Change (5000, Timeout.Infinite);
			client.BeginSend (query.Packet, 0, query.Length, SocketFlags.None, null, null);
		}
Пример #7
0
		void SendAQuery (SimpleResolverEventArgs args, string host, bool add_it)
		{
			DnsQuery query = GetQuery (host, DnsQType.A, DnsQClass.IN);
			SendQuery (args, query, add_it);
		}
Пример #8
0
		void SendAQuery (SimpleResolverEventArgs args, bool add_it)
		{
			SendAQuery (args, args.HostName, add_it);
		}
Пример #9
0
		bool AddQuery (DnsQuery query, SimpleResolverEventArgs args)
		{
			lock (queries) {
				if (queries.ContainsKey (query.Header.ID))
					return false;
				queries [query.Header.ID] = args;
			}
			return true;
		}
Пример #10
0
		// For names -> type A Query
		// For IP addresses -> PTR + A -> will at least return itself
		//	Careful: for IP addresses with PTR, the hostname might yield different IP addresses!
		public bool GetHostEntryAsync (SimpleResolverEventArgs args)
		{
			if (args == null)
				throw new ArgumentNullException ("args");

			if (args.HostName == null)
				throw new ArgumentNullException ("args.HostName is null");

			if (args.HostName.Length > 255)
				throw new ArgumentException ("args.HostName is too long");

			args.Reset (ResolverAsyncOperation.GetHostEntry);
			string host = args.HostName;
			if (host == "") {
				GetLocalHost (args);
				return false;
			}

			IPAddress addr;
			if (IPAddress.TryParse (host, out addr)) {
				IPHostEntry entry = new IPHostEntry ();
				entry.HostName = host;
				entry.Aliases = EmptyStrings;
				entry.AddressList = new IPAddress [1] { addr };
				args.HostEntry = entry;
				args.PTRAddress = addr;
				SendPTRQuery (args, true);
				return true;
			}

			// 3. For IP addresses:
			//	3.1 Parsing IP succeeds
			//	3.2 Reverse lookup of the IP fills in HostName -> fails? HostName = IP
			//	3.3 The hostname resulting from this is used to query DNS again to get the IP addresses
			//
			// Exclude IPv6 addresses if not supported by the system
			// .Aliases is always empty
			// Length > 255
			SendAQuery (args, true);
			return true;
		}
Пример #11
0
		// Type A query
		// Might fill in Aliases
		// -IPAddress -> return the same IPAddress
		// -"" -> Local host ip addresses (filter out IPv6 if needed)
		public bool GetHostAddressesAsync (SimpleResolverEventArgs args)
		{
			if (args == null)
				throw new ArgumentNullException ("args");

			if (args.HostName == null)
				throw new ArgumentNullException ("args.HostName is null");

			if (args.HostName.Length > 255)
				throw new ArgumentException ("args.HostName is too long");

			args.Reset (ResolverAsyncOperation.GetHostAddresses);
			string host = args.HostName;
			if (host == "") {
				GetLocalHost (args);
				return false;
			}
			IPAddress addr;
			if (IPAddress.TryParse (host, out addr)) {
				IPHostEntry entry = new IPHostEntry ();
				entry.HostName = host;
				entry.Aliases = EmptyStrings;
				entry.AddressList = new IPAddress [1] { addr };
				args.HostEntry = entry;
				return false;
			}

			SendAQuery (args, true);
			return true;
		}