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 USA
- using 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();
- }
- }
- }
|