| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 | // This code is derived from jcifs smb client library <jcifs at samba dot org>// Ported by J. Arturo <webmaster at komodosoft dot net>//  // This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 of the License, or (at your option) any later version.// // This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU// Lesser General Public License for more details.// // You should have received a copy of the GNU Lesser General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USAusing System;using System.IO;using System.Linq;using System.Net;using SharpCifs.Netbios;using SharpCifs.Util;using SharpCifs.Util.Sharpen;using Extensions = SharpCifs.Util.Sharpen.Extensions;namespace SharpCifs{	/// <summary>	/// <p>Under normal conditions it is not necessary to use	/// this class to use jCIFS properly.	/// </summary>	/// <remarks>	/// <p>Under normal conditions it is not necessary to use	/// this class to use jCIFS properly. Name resolusion is	/// handled internally to the <code>jcifs.smb</code> package.	/// <p>	/// This class is a wrapper for both	/// <see cref="Jcifs.Netbios.NbtAddress">Jcifs.Netbios.NbtAddress</see>	/// and	/// <see cref="System.Net.IPAddress">System.Net.IPAddress</see>	/// . The name resolution mechanisms	/// used will systematically query all available configured resolution	/// services including WINS, broadcasts, DNS, and LMHOSTS. See	/// <a href="../../resolver.html">Setting Name Resolution Properties</a>	/// and the <code>jcifs.resolveOrder</code> property. Changing	/// jCIFS name resolution properties can greatly affect the behavior of	/// the client and may be necessary for proper operation.	/// <p>	/// This class should be used in favor of <tt>InetAddress</tt> to resolve	/// hostnames on LANs and WANs that support a mixture of NetBIOS/WINS and	/// DNS resolvable hosts.	/// </remarks>	public class UniAddress	{		private const int ResolverWins = 0;		private const int ResolverBcast = 1;		private const int ResolverDns = 2;		private const int ResolverLmhosts = 3;		private static int[] _resolveOrder;		private static IPAddress _baddr;		private static LogStream _log = LogStream.GetInstance();		static UniAddress()		{			string ro = Config.GetProperty("jcifs.resolveOrder");			IPAddress nbns = NbtAddress.GetWinsAddress();			try			{				_baddr = Config.GetInetAddress("jcifs.netbios.baddr", Extensions.GetAddressByName					("255.255.255.255"));			}			catch (UnknownHostException)			{			}			if (string.IsNullOrEmpty(ro))			{				if (nbns == null)				{					_resolveOrder = new int[3];					_resolveOrder[0] = ResolverLmhosts;					_resolveOrder[1] = ResolverDns;					_resolveOrder[2] = ResolverBcast;				}				else				{					_resolveOrder = new int[4];					_resolveOrder[0] = ResolverLmhosts;					_resolveOrder[1] = ResolverWins;					_resolveOrder[2] = ResolverDns;					_resolveOrder[3] = ResolverBcast;				}			}			else			{				int[] tmp = new int[4];				StringTokenizer st = new StringTokenizer(ro, ",");				int i = 0;				while (st.HasMoreTokens())				{					string s = st.NextToken().Trim();					if (Runtime.EqualsIgnoreCase(s, "LMHOSTS"))					{						tmp[i++] = ResolverLmhosts;					}					else					{						if (Runtime.EqualsIgnoreCase(s, "WINS"))						{							if (nbns == null)							{								if (_log.Level > 1)								{									_log.WriteLine("UniAddress resolveOrder specifies WINS however the " + "jcifs.netbios.wins property has not been set"										);								}								continue;							}							tmp[i++] = ResolverWins;						}						else						{							if (Runtime.EqualsIgnoreCase(s, "BCAST"))							{								tmp[i++] = ResolverBcast;							}							else							{								if (Runtime.EqualsIgnoreCase(s, "DNS"))								{									tmp[i++] = ResolverDns;								}								else								{									if (_log.Level > 1)									{										_log.WriteLine("unknown resolver method: " + s);									}								}							}						}					}				}				_resolveOrder = new int[i];				Array.Copy(tmp, 0, _resolveOrder, 0, i);			}		}		internal class Sem		{			internal Sem(int count)			{				this.Count = count;			}			internal int Count;		}		internal class QueryThread : Thread		{			internal Sem Sem;			internal string Host;			internal string Scope;			internal int Type;			internal NbtAddress[] Ans;			internal IPAddress Svr;			internal UnknownHostException Uhe;			internal QueryThread(Sem sem, string host, int type, string scope, IPAddress				 svr) : base("JCIFS-QueryThread: " + host)			{				this.Sem = sem;				this.Host = host;				this.Type = type;				this.Scope = scope;				this.Svr = svr;			}			public override void Run()			{				try				{				    //Ans = new [] { NbtAddress.GetByName(Host, Type, Scope, Svr) };				    Ans = NbtAddress.GetAllByName(Host, Type, Scope, Svr);				}				catch (UnknownHostException uhe)				{					this.Uhe = uhe;				}				catch (Exception ex)				{					Uhe = new UnknownHostException(ex.Message);				}				finally				{					lock (Sem)					{						Sem.Count--;						Runtime.Notify(Sem);					}				}			}		}		/// <exception cref="UnknownHostException"></exception>		internal static NbtAddress[] LookupServerOrWorkgroup(string name, IPAddress svr)		{			Sem sem = new Sem(2);			int type = NbtAddress.IsWins(svr) ? unchecked(0x1b) : unchecked(0x1d);			QueryThread q1X = new QueryThread(sem, name, type, null, svr				);			QueryThread q20 = new QueryThread(sem, name, unchecked(0x20), null, svr);			q1X.SetDaemon(true);			q20.SetDaemon(true);			try			{				lock (sem)				{					q1X.Start();					q20.Start();					while (sem.Count > 0 && q1X.Ans == null && q20.Ans == null)					{						Runtime.Wait(sem);					}				}			}			catch (Exception)			{				throw new UnknownHostException(name);			}			if (q1X.Ans != null)			{				return q1X.Ans;			}		    if (q20.Ans != null)		    {		        return q20.Ans;		    }		    throw q1X.Uhe;		}		/// <summary>Determines the address of a host given it's host name.</summary>		/// <remarks>		/// Determines the address of a host given it's host name. The name can be a		/// machine name like "jcifs.samba.org",  or an IP address like "192.168.1.15".		/// </remarks>		/// <param name="hostname">NetBIOS or DNS hostname to resolve</param>		/// <exception cref="UnknownHostException">if there is an error resolving the name		/// 	</exception>		public static UniAddress GetByName(string hostname)		{			return GetByName(hostname, false);		}		internal static bool IsDotQuadIp(string hostname)		{			if (char.IsDigit(hostname[0]))			{				int i;				int len;				int dots;				char[] data;				i = dots = 0;				len = hostname.Length;				data = hostname.ToCharArray();				while (i < len && char.IsDigit(data[i++]))				{					if (i == len && dots == 3)					{						// probably an IP address						return true;					}					if (i < len && data[i] == '.')					{						dots++;						i++;					}				}			}			return false;		}		internal static bool IsAllDigits(string hostname)		{			for (int i = 0; i < hostname.Length; i++)			{				if (char.IsDigit(hostname[i]) == false)				{					return false;				}			}			return true;		}		/// <summary>Lookup <tt>hostname</tt> and return it's <tt>UniAddress</tt>.</summary>		/// <remarks>		/// Lookup <tt>hostname</tt> and return it's <tt>UniAddress</tt>. If the		/// <tt>possibleNTDomainOrWorkgroup</tt> parameter is <tt>true</tt> an		/// addtional name query will be performed to locate a master browser.		/// </remarks>		/// <exception cref="UnknownHostException"></exception>		public static UniAddress GetByName(string hostname, bool possibleNtDomainOrWorkgroup			)		{			UniAddress[] addrs = GetAllByName(hostname, possibleNtDomainOrWorkgroup				);			return addrs[0];		}		/// <exception cref="UnknownHostException"></exception>		public static UniAddress[] GetAllByName(string hostname, bool possibleNtDomainOrWorkgroup			)		{			object addr;			int i;			if (string.IsNullOrEmpty(hostname))			{				throw new UnknownHostException();			}			if (IsDotQuadIp(hostname))			{				UniAddress[] addrs = new UniAddress[1];				addrs[0] = new UniAddress(NbtAddress.GetByName(hostname));				return addrs;			}			for (i = 0; i < _resolveOrder.Length; i++)			{				try				{					switch (_resolveOrder[i])					{						case ResolverLmhosts:						{							if ((addr = Lmhosts.GetByName(hostname)) == null)							{								continue;							}							break;						}						case ResolverWins:						{							if (hostname == NbtAddress.MasterBrowserName || hostname.Length > 15)							{								// invalid netbios name								continue;							}							if (possibleNtDomainOrWorkgroup)							{								addr = LookupServerOrWorkgroup(hostname, NbtAddress.GetWinsAddress());							}							else							{								addr = NbtAddress.GetByName(hostname, unchecked(0x20), null, NbtAddress.GetWinsAddress									());							}							break;						}						case ResolverBcast:						{							if (hostname.Length > 15)							{								// invalid netbios name								continue;							}						    try						    {                                if (possibleNtDomainOrWorkgroup)                                {                                    NbtAddress[] iaddrs = LookupServerOrWorkgroup(hostname, _baddr);                                    UniAddress[] addrs = new UniAddress[iaddrs.Length];                                    for (int ii = 0; ii < iaddrs.Length; ii++)                                    {                                        addrs[ii] = new UniAddress(iaddrs[ii]);                                    }                                    return addrs;                                }                                else                                {                                    addr = NbtAddress.GetByName(hostname, unchecked(0x20), null, _baddr);                                }						    }						    catch (Exception ex)						    {						        if (i == _resolveOrder.Length - 1)						        {						            throw ex;						        }						        else						        {						            continue;						        }						    }							break;						}						case ResolverDns:						{							if (IsAllDigits(hostname))							{								throw new UnknownHostException(hostname);							}                            IPAddress[] iaddrs = Extensions.GetAddressesByName(hostname);                            if (iaddrs == null || iaddrs.Length == 0)                            {                                continue;                            }                            return iaddrs.Select(iaddr => new UniAddress(iaddr)).ToArray();                            						}						default:						{							// Success							throw new UnknownHostException(hostname);						}					}					UniAddress[] addrs1 = new UniAddress[1];					addrs1[0] = new UniAddress(addr);					return addrs1;				}				catch (IOException)				{				}			}			// Success			// Failure			throw new UnknownHostException(hostname);		}		internal object Addr;		internal string CalledName;		/// <summary>		/// Create a <tt>UniAddress</tt> by wrapping an <tt>InetAddress</tt> or		/// <tt>NbtAddress</tt>.		/// </summary>		/// <remarks>		/// Create a <tt>UniAddress</tt> by wrapping an <tt>InetAddress</tt> or		/// <tt>NbtAddress</tt>.		/// </remarks>		public UniAddress(object addr)		{			if (addr == null)			{				throw new ArgumentException();			}			this.Addr = addr;		}		/// <summary>Return the IP address of this address as a 32 bit integer.</summary>		/// <remarks>Return the IP address of this address as a 32 bit integer.</remarks>		public override int GetHashCode()		{			return Addr.GetHashCode();		}		/// <summary>Compare two addresses for equality.</summary>		/// <remarks>		/// Compare two addresses for equality. Two <tt>UniAddress</tt>s are equal		/// if they are both <tt>UniAddress</tt>' and refer to the same IP address.		/// </remarks>		public override bool Equals(object obj)		{			return obj is UniAddress && Addr.Equals(((UniAddress)obj).Addr);		}		/// <summary>Guess first called name to try for session establishment.</summary>		/// <remarks>		/// Guess first called name to try for session establishment. This		/// method is used exclusively by the <tt>jcifs.smb</tt> package.		/// </remarks>		public virtual string FirstCalledName()		{			if (Addr is NbtAddress)			{				return ((NbtAddress)Addr).FirstCalledName();			}		    CalledName = ((IPAddress) Addr).GetHostAddress();		    if (IsDotQuadIp(CalledName))		    {		        CalledName = NbtAddress.SmbserverName;		    }		    else		    {		        int i = CalledName.IndexOf('.');		        if (i > 1 && i < 15)		        {		            CalledName = Runtime.Substring(CalledName, 0, i).ToUpper();		        }		        else		        {		            if (CalledName.Length > 15)		            {		                CalledName = NbtAddress.SmbserverName;		            }		            else		            {		                CalledName = CalledName.ToUpper();		            }		        }		    }		    return CalledName;		}		/// <summary>Guess next called name to try for session establishment.</summary>		/// <remarks>		/// Guess next called name to try for session establishment. This		/// method is used exclusively by the <tt>jcifs.smb</tt> package.		/// </remarks>		public virtual string NextCalledName()		{			if (Addr is NbtAddress)			{				return ((NbtAddress)Addr).NextCalledName();			}		    if (CalledName != NbtAddress.SmbserverName)		    {		        CalledName = NbtAddress.SmbserverName;		        return CalledName;		    }		    return null;		}		/// <summary>Return the underlying <tt>NbtAddress</tt> or <tt>InetAddress</tt>.</summary>		/// <remarks>Return the underlying <tt>NbtAddress</tt> or <tt>InetAddress</tt>.</remarks>		public virtual object GetAddress()		{			return Addr;		}		/// <summary>Return the hostname of this address such as "MYCOMPUTER".</summary>		/// <remarks>Return the hostname of this address such as "MYCOMPUTER".</remarks>		public virtual string GetHostName()		{			if (Addr is NbtAddress)			{				return ((NbtAddress)Addr).GetHostName();			}		    return ((IPAddress) Addr).GetHostAddress();		}		/// <summary>Return the IP address as text such as "192.168.1.15".</summary>		/// <remarks>Return the IP address as text such as "192.168.1.15".</remarks>		public virtual string GetHostAddress()		{			if (Addr is NbtAddress)			{				return ((NbtAddress)Addr).GetHostAddress();			}			return ((IPAddress)Addr).GetHostAddress();		}	    public virtual IPAddress GetHostIpAddress()	    {	        return (IPAddress) Addr;	    }		/// <summary>		/// Return the a text representation of this address such as		/// <tt>MYCOMPUTER/192.168.1.15</tt>.		/// </summary>		/// <remarks>		/// Return the a text representation of this address such as		/// <tt>MYCOMPUTER/192.168.1.15</tt>.		/// </remarks>		public override string ToString()		{			return Addr.ToString();		}	}}
 |