NbtAddress.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. // This code is derived from jcifs smb client library <jcifs at samba dot org>
  2. // Ported by J. Arturo <webmaster at komodosoft dot net>
  3. //
  4. // This library is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Lesser General Public
  6. // License as published by the Free Software Foundation; either
  7. // version 2.1 of the License, or (at your option) any later version.
  8. //
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. // Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public
  15. // License along with this library; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. using System;
  18. using System.Linq;
  19. using System.Net;
  20. using SharpCifs.Util;
  21. using SharpCifs.Util.Sharpen;
  22. using Extensions = SharpCifs.Util.Sharpen.Extensions;
  23. namespace SharpCifs.Netbios
  24. {
  25. /// <summary>This class represents a NetBIOS over TCP/IP address.</summary>
  26. /// <remarks>
  27. /// This class represents a NetBIOS over TCP/IP address. Under normal
  28. /// conditions, users of jCIFS need not be concerned with this class as
  29. /// name resolution and session services are handled internally by the smb package.
  30. /// <p> Applications can use the methods <code>getLocalHost</code>,
  31. /// <code>getByName</code>, and
  32. /// <code>getAllByAddress</code> to create a new NbtAddress instance. This
  33. /// class is symmetric with
  34. /// <see cref="System.Net.IPAddress">System.Net.IPAddress</see>
  35. /// .
  36. /// <p><b>About NetBIOS:</b> The NetBIOS name
  37. /// service is a dynamic distributed service that allows hosts to resolve
  38. /// names by broadcasting a query, directing queries to a server such as
  39. /// Samba or WINS. NetBIOS is currently the primary networking layer for
  40. /// providing name service, datagram service, and session service to the
  41. /// Microsoft Windows platform. A NetBIOS name can be 15 characters long
  42. /// and hosts usually registers several names on the network. From a
  43. /// Windows command prompt you can see
  44. /// what names a host registers with the nbtstat command.
  45. /// <p><blockquote><pre>
  46. /// C:\&gt;nbtstat -a 192.168.1.15
  47. /// NetBIOS Remote Machine Name Table
  48. /// Name Type Status
  49. /// ---------------------------------------------
  50. /// JMORRIS2 <00> UNIQUE Registered
  51. /// BILLING-NY <00> GROUP Registered
  52. /// JMORRIS2 <03> UNIQUE Registered
  53. /// JMORRIS2 <20> UNIQUE Registered
  54. /// BILLING-NY <1E> GROUP Registered
  55. /// JMORRIS <03> UNIQUE Registered
  56. /// MAC Address = 00-B0-34-21-FA-3B
  57. /// </blockquote></pre>
  58. /// <p> The hostname of this machine is <code>JMORRIS2</code>. It is
  59. /// a member of the group(a.k.a workgroup and domain) <code>BILLING-NY</code>. To
  60. /// obtain an
  61. /// <see cref="System.Net.IPAddress">System.Net.IPAddress</see>
  62. /// for a host one might do:
  63. /// <pre>
  64. /// InetAddress addr = NbtAddress.getByName( "jmorris2" ).getInetAddress();
  65. /// </pre>
  66. /// <p>From a UNIX platform with Samba installed you can perform similar
  67. /// diagnostics using the <code>nmblookup</code> utility.
  68. /// </remarks>
  69. /// <author>Michael B. Allen</author>
  70. /// <seealso cref="System.Net.IPAddress">System.Net.IPAddress</seealso>
  71. /// <since>jcifs-0.1</since>
  72. public sealed class NbtAddress
  73. {
  74. internal static readonly string AnyHostsName = "*\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000";
  75. /// <summary>
  76. /// This is a special name for querying the master browser that serves the
  77. /// list of hosts found in "Network Neighborhood".
  78. /// </summary>
  79. /// <remarks>
  80. /// This is a special name for querying the master browser that serves the
  81. /// list of hosts found in "Network Neighborhood".
  82. /// </remarks>
  83. public static readonly string MasterBrowserName = "\u0001\u0002__MSBROWSE__\u0002";
  84. /// <summary>
  85. /// A special generic name specified when connecting to a host for which
  86. /// a name is not known.
  87. /// </summary>
  88. /// <remarks>
  89. /// A special generic name specified when connecting to a host for which
  90. /// a name is not known. Not all servers respond to this name.
  91. /// </remarks>
  92. public static readonly string SmbserverName = "*SMBSERVER ";
  93. /// <summary>A B node only broadcasts name queries.</summary>
  94. /// <remarks>
  95. /// A B node only broadcasts name queries. This is the default if a
  96. /// nameserver such as WINS or Samba is not specified.
  97. /// </remarks>
  98. public const int BNode = 0;
  99. /// <summary>
  100. /// A Point-to-Point node, or P node, unicasts queries to a nameserver
  101. /// only.
  102. /// </summary>
  103. /// <remarks>
  104. /// A Point-to-Point node, or P node, unicasts queries to a nameserver
  105. /// only. Natrually the <code>jcifs.netbios.nameserver</code> property must
  106. /// be set.
  107. /// </remarks>
  108. public const int PNode = 1;
  109. /// <summary>
  110. /// Try Broadcast queries first, then try to resolve the name using the
  111. /// nameserver.
  112. /// </summary>
  113. /// <remarks>
  114. /// Try Broadcast queries first, then try to resolve the name using the
  115. /// nameserver.
  116. /// </remarks>
  117. public const int MNode = 2;
  118. /// <summary>A Hybrid node tries to resolve a name using the nameserver first.</summary>
  119. /// <remarks>
  120. /// A Hybrid node tries to resolve a name using the nameserver first. If
  121. /// that fails use the broadcast address. This is the default if a nameserver
  122. /// is provided. This is the behavior of Microsoft Windows machines.
  123. /// </remarks>
  124. public const int HNode = 3;
  125. internal static readonly IPAddress[] Nbns = Config.GetInetAddressArray("jcifs.netbios.wins"
  126. , ",", new IPAddress[0]);
  127. private static readonly NameServiceClient Client = new NameServiceClient();
  128. private const int DefaultCachePolicy = 30;
  129. private static readonly int CachePolicy = Config.GetInt("jcifs.netbios.cachePolicy"
  130. , DefaultCachePolicy);
  131. private const int Forever = -1;
  132. private static int _nbnsIndex;
  133. private static readonly Hashtable AddressCache = new Hashtable();
  134. private static readonly Hashtable LookupTable = new Hashtable();
  135. internal static readonly Name UnknownName = new Name("0.0.0.0", unchecked(0x00), null);
  136. internal static readonly NbtAddress UnknownAddress = new NbtAddress
  137. (UnknownName, 0, false, BNode);
  138. internal static readonly byte[] UnknownMacAddress = { unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)) };
  139. internal sealed class CacheEntry
  140. {
  141. internal Name HostName;
  142. internal NbtAddress Address;
  143. internal long Expiration;
  144. internal CacheEntry(Name hostName, NbtAddress address, long expiration)
  145. {
  146. this.HostName = hostName;
  147. this.Address = address;
  148. this.Expiration = expiration;
  149. }
  150. }
  151. internal static NbtAddress Localhost;
  152. static NbtAddress()
  153. {
  154. IPAddress localInetAddress;
  155. string localHostname;
  156. Name localName;
  157. AddressCache.Put(UnknownName, new CacheEntry(UnknownName, UnknownAddress
  158. , Forever));
  159. localInetAddress = Client.laddr;
  160. if (localInetAddress == null)
  161. {
  162. try
  163. {
  164. localInetAddress = Extensions.GetAddressByName("127.0.0.1");
  165. }
  166. catch (UnknownHostException)
  167. {
  168. }
  169. }
  170. localHostname = Config.GetProperty("jcifs.netbios.hostname", null);
  171. if (string.IsNullOrEmpty(localHostname))
  172. {
  173. byte[] addr = localInetAddress.GetAddressBytes();
  174. /*localHostname = "JCIFS" + (addr[2] & unchecked((int)(0xFF))) + "_" + (addr[3] & unchecked(
  175. (int)(0xFF))) + "_" + Hexdump.ToHexString((int)(new Random().NextDouble() * (double)unchecked(
  176. (int)(0xFF))), 2);*/
  177. localHostname = "JCIFS_127_0_0_1";
  178. }
  179. localName = new Name(localHostname, unchecked(0x00), Config.GetProperty("jcifs.netbios.scope"
  180. , null));
  181. Localhost = new NbtAddress(localName, localInetAddress.GetHashCode(), false, BNode
  182. , false, false, true, false, UnknownMacAddress);
  183. CacheAddress(localName, Localhost, Forever);
  184. }
  185. internal static void CacheAddress(Name hostName, NbtAddress addr)
  186. {
  187. if (CachePolicy == 0)
  188. {
  189. return;
  190. }
  191. long expiration = -1;
  192. if (CachePolicy != Forever)
  193. {
  194. expiration = Runtime.CurrentTimeMillis() + CachePolicy * 1000;
  195. }
  196. CacheAddress(hostName, addr, expiration);
  197. }
  198. internal static void CacheAddress(Name hostName, NbtAddress addr, long expiration
  199. )
  200. {
  201. if (CachePolicy == 0)
  202. {
  203. return;
  204. }
  205. lock (AddressCache)
  206. {
  207. CacheEntry entry = (CacheEntry)AddressCache.Get(hostName);
  208. if (entry == null)
  209. {
  210. entry = new CacheEntry(hostName, addr, expiration);
  211. AddressCache.Put(hostName, entry);
  212. }
  213. else
  214. {
  215. entry.Address = addr;
  216. entry.Expiration = expiration;
  217. }
  218. }
  219. }
  220. internal static void CacheAddressArray(NbtAddress[] addrs)
  221. {
  222. if (CachePolicy == 0)
  223. {
  224. return;
  225. }
  226. long expiration = -1;
  227. if (CachePolicy != Forever)
  228. {
  229. expiration = Runtime.CurrentTimeMillis() + CachePolicy * 1000;
  230. }
  231. lock (AddressCache)
  232. {
  233. for (int i = 0; i < addrs.Length; i++)
  234. {
  235. CacheEntry entry = (CacheEntry)AddressCache.Get(addrs[i].HostName
  236. );
  237. if (entry == null)
  238. {
  239. entry = new CacheEntry(addrs[i].HostName, addrs[i], expiration);
  240. AddressCache.Put(addrs[i].HostName, entry);
  241. }
  242. else
  243. {
  244. entry.Address = addrs[i];
  245. entry.Expiration = expiration;
  246. }
  247. }
  248. }
  249. }
  250. internal static NbtAddress GetCachedAddress(Name hostName)
  251. {
  252. if (CachePolicy == 0)
  253. {
  254. return null;
  255. }
  256. lock (AddressCache)
  257. {
  258. CacheEntry entry = (CacheEntry)AddressCache.Get(hostName);
  259. if (entry != null && entry.Expiration < Runtime.CurrentTimeMillis() && entry.Expiration
  260. >= 0)
  261. {
  262. entry = null;
  263. }
  264. return entry != null ? entry.Address : null;
  265. }
  266. }
  267. /// <exception cref="UnknownHostException"></exception>
  268. internal static NbtAddress DoNameQuery(Name name, IPAddress svr)
  269. {
  270. NbtAddress addr;
  271. if (name.HexCode == unchecked(0x1d) && svr == null)
  272. {
  273. svr = Client.Baddr;
  274. }
  275. // bit of a hack but saves a lookup
  276. name.SrcHashCode = svr != null ? svr.GetHashCode() : 0;
  277. addr = GetCachedAddress(name);
  278. if (addr == null)
  279. {
  280. if ((addr = (NbtAddress)CheckLookupTable(name)) == null)
  281. {
  282. try
  283. {
  284. addr = Client.GetByName(name, svr);
  285. }
  286. catch (UnknownHostException)
  287. {
  288. addr = UnknownAddress;
  289. }
  290. finally
  291. {
  292. CacheAddress(name, addr);
  293. UpdateLookupTable(name);
  294. }
  295. }
  296. }
  297. if (addr == UnknownAddress)
  298. {
  299. throw new UnknownHostException(name.ToString());
  300. }
  301. return addr;
  302. }
  303. private static object CheckLookupTable(Name name)
  304. {
  305. object obj;
  306. lock (LookupTable)
  307. {
  308. if (LookupTable.ContainsKey(name) == false)
  309. {
  310. LookupTable.Put(name, name);
  311. return null;
  312. }
  313. while (LookupTable.ContainsKey(name))
  314. {
  315. try
  316. {
  317. Runtime.Wait(LookupTable);
  318. }
  319. catch (Exception)
  320. {
  321. }
  322. }
  323. }
  324. obj = GetCachedAddress(name);
  325. if (obj == null)
  326. {
  327. lock (LookupTable)
  328. {
  329. LookupTable.Put(name, name);
  330. }
  331. }
  332. return obj;
  333. }
  334. private static void UpdateLookupTable(Name name)
  335. {
  336. lock (LookupTable)
  337. {
  338. //Sharpen.Collections.Remove(LOOKUP_TABLE, name);
  339. LookupTable.Remove(name);
  340. Runtime.NotifyAll(LookupTable);
  341. }
  342. }
  343. /// <summary>Retrieves the local host address.</summary>
  344. /// <remarks>Retrieves the local host address.</remarks>
  345. /// <exception cref="UnknownHostException">
  346. /// This is not likely as the IP returned
  347. /// by <code>InetAddress</code> should be available
  348. /// </exception>
  349. public static NbtAddress GetLocalHost()
  350. {
  351. return Localhost;
  352. }
  353. public static NbtAddress[] GetHosts()
  354. {
  355. return new NameServiceClient().GetHosts();
  356. }
  357. public static Name GetLocalName()
  358. {
  359. return Localhost.HostName;
  360. }
  361. /// <summary>Determines the address of a host given it's host name.</summary>
  362. /// <remarks>
  363. /// Determines the address of a host given it's host name. The name can be a NetBIOS name like
  364. /// "freto" or an IP address like "192.168.1.15". It cannot be a DNS name;
  365. /// the analygous
  366. /// <see cref="SharpCifs.UniAddress">Jcifs.UniAddress</see>
  367. /// or
  368. /// <see cref="System.Net.IPAddress">System.Net.IPAddress</see>
  369. /// <code>getByName</code> methods can be used for that.
  370. /// </remarks>
  371. /// <param name="host">hostname to resolve</param>
  372. /// <exception cref="UnknownHostException">if there is an error resolving the name
  373. /// </exception>
  374. public static NbtAddress GetByName(string host)
  375. {
  376. return GetByName(host, unchecked(0x00), null);
  377. }
  378. /// <summary>Determines the address of a host given it's host name.</summary>
  379. /// <remarks>
  380. /// Determines the address of a host given it's host name. NetBIOS
  381. /// names also have a <code>type</code>. Types(aka Hex Codes)
  382. /// are used to distiquish the various services on a host. &lt;a
  383. /// href="../../../nbtcodes.html"&gt;Here</a> is
  384. /// a fairly complete list of NetBIOS hex codes. Scope is not used but is
  385. /// still functional in other NetBIOS products and so for completeness it has been
  386. /// implemented. A <code>scope</code> of <code>null</code> or <code>""</code>
  387. /// signifies no scope.
  388. /// </remarks>
  389. /// <param name="host">the name to resolve</param>
  390. /// <param name="type">the hex code of the name</param>
  391. /// <param name="scope">the scope of the name</param>
  392. /// <exception cref="UnknownHostException">if there is an error resolving the name
  393. /// </exception>
  394. public static NbtAddress GetByName(string host, int type, string scope)
  395. {
  396. return GetByName(host, type, scope, null);
  397. }
  398. /// <exception cref="UnknownHostException"></exception>
  399. public static NbtAddress GetByName(string host, int type, string scope, IPAddress
  400. svr)
  401. {
  402. if (string.IsNullOrEmpty(host))
  403. {
  404. return GetLocalHost();
  405. }
  406. if (!char.IsDigit(host[0]))
  407. {
  408. return DoNameQuery(new Name(host, type, scope), svr);
  409. }
  410. int ip = unchecked(0x00);
  411. int hitDots = 0;
  412. char[] data = host.ToCharArray();
  413. for (int i = 0; i < data.Length; i++)
  414. {
  415. char c = data[i];
  416. if (c < 48 || c > 57)
  417. {
  418. return DoNameQuery(new Name(host, type, scope), svr);
  419. }
  420. int b = unchecked(0x00);
  421. while (c != '.')
  422. {
  423. if (c < 48 || c > 57)
  424. {
  425. return DoNameQuery(new Name(host, type, scope), svr);
  426. }
  427. b = b * 10 + c - '0';
  428. if (++i >= data.Length)
  429. {
  430. break;
  431. }
  432. c = data[i];
  433. }
  434. if (b > unchecked(0xFF))
  435. {
  436. return DoNameQuery(new Name(host, type, scope), svr);
  437. }
  438. ip = (ip << 8) + b;
  439. hitDots++;
  440. }
  441. if (hitDots != 4 || host.EndsWith("."))
  442. {
  443. return DoNameQuery(new Name(host, type, scope), svr);
  444. }
  445. return new NbtAddress(UnknownName, ip, false, BNode);
  446. }
  447. /// <exception cref="UnknownHostException"></exception>
  448. public static NbtAddress[] GetAllByName(string host, int type, string scope, IPAddress
  449. svr)
  450. {
  451. return Client.GetAllByName(new Name(host, type, scope), svr);
  452. }
  453. /// <summary>Retrieve all addresses of a host by it's address.</summary>
  454. /// <remarks>
  455. /// Retrieve all addresses of a host by it's address. NetBIOS hosts can
  456. /// have many names for a given IP address. The name and IP address make the
  457. /// NetBIOS address. This provides a way to retrieve the other names for a
  458. /// host with the same IP address.
  459. /// </remarks>
  460. /// <param name="host">hostname to lookup all addresses for</param>
  461. /// <exception cref="UnknownHostException">if there is an error resolving the name
  462. /// </exception>
  463. public static NbtAddress[] GetAllByAddress(string host)
  464. {
  465. return GetAllByAddress(GetByName(host, unchecked(0x00), null));
  466. }
  467. /// <summary>Retrieve all addresses of a host by it's address.</summary>
  468. /// <remarks>
  469. /// Retrieve all addresses of a host by it's address. NetBIOS hosts can
  470. /// have many names for a given IP address. The name and IP address make
  471. /// the NetBIOS address. This provides a way to retrieve the other names
  472. /// for a host with the same IP address. See
  473. /// <see cref="GetByName(string)">GetByName(string)</see>
  474. /// for a description of <code>type</code>
  475. /// and <code>scope</code>.
  476. /// </remarks>
  477. /// <param name="host">hostname to lookup all addresses for</param>
  478. /// <param name="type">the hexcode of the name</param>
  479. /// <param name="scope">the scope of the name</param>
  480. /// <exception cref="UnknownHostException">if there is an error resolving the name
  481. /// </exception>
  482. public static NbtAddress[] GetAllByAddress(string host, int type, string scope)
  483. {
  484. return GetAllByAddress(GetByName(host, type, scope));
  485. }
  486. /// <summary>Retrieve all addresses of a host by it's address.</summary>
  487. /// <remarks>
  488. /// Retrieve all addresses of a host by it's address. NetBIOS hosts can
  489. /// have many names for a given IP address. The name and IP address make the
  490. /// NetBIOS address. This provides a way to retrieve the other names for a
  491. /// host with the same IP address.
  492. /// </remarks>
  493. /// <param name="addr">the address to query</param>
  494. /// <exception cref="UnknownHostException">if address cannot be resolved</exception>
  495. public static NbtAddress[] GetAllByAddress(NbtAddress addr)
  496. {
  497. try
  498. {
  499. NbtAddress[] addrs = Client.GetNodeStatus(addr);
  500. CacheAddressArray(addrs);
  501. return addrs;
  502. }
  503. catch (UnknownHostException)
  504. {
  505. throw new UnknownHostException("no name with type 0x" + Hexdump.ToHexString(addr.
  506. HostName.HexCode, 2) + (((addr.HostName.Scope == null) || (addr.HostName.Scope.Length
  507. == 0)) ? " with no scope" : " with scope " + addr.HostName.Scope) + " for host "
  508. + addr.GetHostAddress());
  509. }
  510. }
  511. public static IPAddress GetWinsAddress()
  512. {
  513. return Nbns.Length == 0 ? null : Nbns[_nbnsIndex];
  514. }
  515. public static bool IsWins(IPAddress svr)
  516. {
  517. for (int i = 0; svr != null && i < Nbns.Length; i++)
  518. {
  519. if (svr.GetHashCode() == Nbns[i].GetHashCode())
  520. {
  521. return true;
  522. }
  523. }
  524. return false;
  525. }
  526. internal static IPAddress SwitchWins()
  527. {
  528. _nbnsIndex = (_nbnsIndex + 1) < Nbns.Length ? _nbnsIndex + 1 : 0;
  529. return Nbns.Length == 0 ? null : Nbns[_nbnsIndex];
  530. }
  531. internal Name HostName;
  532. internal int Address;
  533. internal int NodeType;
  534. internal bool GroupName;
  535. internal bool isBeingDeleted;
  536. internal bool isInConflict;
  537. internal bool isActive;
  538. internal bool isPermanent;
  539. internal bool IsDataFromNodeStatus;
  540. internal byte[] MacAddress;
  541. internal string CalledName;
  542. internal NbtAddress(Name hostName, int address, bool groupName, int nodeType)
  543. {
  544. this.HostName = hostName;
  545. this.Address = address;
  546. this.GroupName = groupName;
  547. this.NodeType = nodeType;
  548. }
  549. internal NbtAddress(Name hostName, int address, bool groupName, int nodeType, bool
  550. isBeingDeleted, bool isInConflict, bool isActive, bool isPermanent, byte[] macAddress
  551. )
  552. {
  553. this.HostName = hostName;
  554. this.Address = address;
  555. this.GroupName = groupName;
  556. this.NodeType = nodeType;
  557. this.isBeingDeleted = isBeingDeleted;
  558. this.isInConflict = isInConflict;
  559. this.isActive = isActive;
  560. this.isPermanent = isPermanent;
  561. this.MacAddress = macAddress;
  562. IsDataFromNodeStatus = true;
  563. }
  564. public string FirstCalledName()
  565. {
  566. CalledName = HostName.name;
  567. if (char.IsDigit(CalledName[0]))
  568. {
  569. int i;
  570. int len;
  571. int dots;
  572. char[] data;
  573. i = dots = 0;
  574. len = CalledName.Length;
  575. data = CalledName.ToCharArray();
  576. while (i < len && char.IsDigit(data[i++]))
  577. {
  578. if (i == len && dots == 3)
  579. {
  580. // probably an IP address
  581. CalledName = SmbserverName;
  582. break;
  583. }
  584. if (i < len && data[i] == '.')
  585. {
  586. dots++;
  587. i++;
  588. }
  589. }
  590. }
  591. else
  592. {
  593. switch (HostName.HexCode)
  594. {
  595. case unchecked(0x1B):
  596. case unchecked(0x1C):
  597. case unchecked(0x1D):
  598. {
  599. CalledName = SmbserverName;
  600. break;
  601. }
  602. }
  603. }
  604. return CalledName;
  605. }
  606. public string NextCalledName()
  607. {
  608. if (CalledName == HostName.name)
  609. {
  610. CalledName = SmbserverName;
  611. }
  612. else
  613. {
  614. if (CalledName == SmbserverName)
  615. {
  616. NbtAddress[] addrs;
  617. try
  618. {
  619. addrs = Client.GetNodeStatus(this);
  620. if (HostName.HexCode == unchecked(0x1D))
  621. {
  622. for (int i = 0; i < addrs.Length; i++)
  623. {
  624. if (addrs[i].HostName.HexCode == unchecked(0x20))
  625. {
  626. return addrs[i].HostName.name;
  627. }
  628. }
  629. return null;
  630. }
  631. if (IsDataFromNodeStatus)
  632. {
  633. CalledName = null;
  634. return HostName.name;
  635. }
  636. }
  637. catch (UnknownHostException)
  638. {
  639. CalledName = null;
  640. }
  641. }
  642. else
  643. {
  644. CalledName = null;
  645. }
  646. }
  647. return CalledName;
  648. }
  649. /// <exception cref="UnknownHostException"></exception>
  650. internal void CheckData()
  651. {
  652. if (HostName == UnknownName)
  653. {
  654. GetAllByAddress(this);
  655. }
  656. }
  657. /// <exception cref="UnknownHostException"></exception>
  658. internal void CheckNodeStatusData()
  659. {
  660. if (IsDataFromNodeStatus == false)
  661. {
  662. GetAllByAddress(this);
  663. }
  664. }
  665. /// <summary>Determines if the address is a group address.</summary>
  666. /// <remarks>
  667. /// Determines if the address is a group address. This is also
  668. /// known as a workgroup name or group name.
  669. /// </remarks>
  670. /// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
  671. /// </exception>
  672. public bool IsGroupAddress()
  673. {
  674. CheckData();
  675. return GroupName;
  676. }
  677. /// <summary>Checks the node type of this address.</summary>
  678. /// <remarks>Checks the node type of this address.</remarks>
  679. /// <returns>
  680. ///
  681. /// <see cref="BNode">B_NODE</see>
  682. /// ,
  683. /// <see cref="PNode">P_NODE</see>
  684. /// ,
  685. /// <see cref="MNode">M_NODE</see>
  686. /// ,
  687. /// <see cref="HNode">H_NODE</see>
  688. /// </returns>
  689. /// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
  690. /// </exception>
  691. public int GetNodeType()
  692. {
  693. CheckData();
  694. return NodeType;
  695. }
  696. /// <summary>Determines if this address in the process of being deleted.</summary>
  697. /// <remarks>Determines if this address in the process of being deleted.</remarks>
  698. /// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
  699. /// </exception>
  700. public bool IsBeingDeleted()
  701. {
  702. CheckNodeStatusData();
  703. return isBeingDeleted;
  704. }
  705. /// <summary>Determines if this address in conflict with another address.</summary>
  706. /// <remarks>Determines if this address in conflict with another address.</remarks>
  707. /// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
  708. /// </exception>
  709. public bool IsInConflict()
  710. {
  711. CheckNodeStatusData();
  712. return isInConflict;
  713. }
  714. /// <summary>Determines if this address is active.</summary>
  715. /// <remarks>Determines if this address is active.</remarks>
  716. /// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
  717. /// </exception>
  718. public bool IsActive()
  719. {
  720. CheckNodeStatusData();
  721. return isActive;
  722. }
  723. /// <summary>Determines if this address is set to be permanent.</summary>
  724. /// <remarks>Determines if this address is set to be permanent.</remarks>
  725. /// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
  726. /// </exception>
  727. public bool IsPermanent()
  728. {
  729. CheckNodeStatusData();
  730. return isPermanent;
  731. }
  732. /// <summary>Retrieves the MAC address of the remote network interface.</summary>
  733. /// <remarks>Retrieves the MAC address of the remote network interface. Samba returns all zeros.
  734. /// </remarks>
  735. /// <returns>the MAC address as an array of six bytes</returns>
  736. /// <exception cref="UnknownHostException">
  737. /// if the host cannot be resolved to
  738. /// determine the MAC address.
  739. /// </exception>
  740. public byte[] GetMacAddress()
  741. {
  742. CheckNodeStatusData();
  743. return MacAddress;
  744. }
  745. /// <summary>The hostname of this address.</summary>
  746. /// <remarks>
  747. /// The hostname of this address. If the hostname is null the local machines
  748. /// IP address is returned.
  749. /// </remarks>
  750. /// <returns>the text representation of the hostname associated with this address</returns>
  751. public string GetHostName()
  752. {
  753. if (HostName == UnknownName)
  754. {
  755. return GetHostAddress();
  756. }
  757. return HostName.name;
  758. }
  759. /// <summary>Returns the raw IP address of this NbtAddress.</summary>
  760. /// <remarks>
  761. /// Returns the raw IP address of this NbtAddress. The result is in network
  762. /// byte order: the highest order byte of the address is in getAddress()[0].
  763. /// </remarks>
  764. /// <returns>a four byte array</returns>
  765. public byte[] GetAddress()
  766. {
  767. byte[] addr = new byte[4];
  768. addr[0] = unchecked((byte)(((int)(((uint)Address) >> 24)) & unchecked(0xFF
  769. )));
  770. addr[1] = unchecked((byte)(((int)(((uint)Address) >> 16)) & unchecked(0xFF
  771. )));
  772. addr[2] = unchecked((byte)(((int)(((uint)Address) >> 8)) & unchecked(0xFF)
  773. ));
  774. addr[3] = unchecked((byte)(Address & unchecked(0xFF)));
  775. return addr;
  776. }
  777. /// <summary>To convert this address to an <code>InetAddress</code>.</summary>
  778. /// <remarks>To convert this address to an <code>InetAddress</code>.</remarks>
  779. /// <returns>
  780. /// the
  781. /// <see cref="System.Net.IPAddress">System.Net.IPAddress</see>
  782. /// representation of this address.
  783. /// </returns>
  784. /// <exception cref="UnknownHostException"></exception>
  785. public IPAddress GetInetAddress()
  786. {
  787. return Extensions.GetAddressByName(GetHostAddress());
  788. }
  789. /// <summary>
  790. /// Returns this IP adress as a
  791. /// <see cref="string">string</see>
  792. /// in the form "%d.%d.%d.%d".
  793. /// </summary>
  794. public string GetHostAddress()
  795. {
  796. return (((int)(((uint)Address) >> 24)) & unchecked(0xFF)) + "." + (((int)(
  797. ((uint)Address) >> 16)) & unchecked(0xFF)) + "." + (((int)(((uint)Address
  798. ) >> 8)) & unchecked(0xFF)) + "." + (((int)(((uint)Address) >> 0)) & unchecked(
  799. 0xFF));
  800. }
  801. /// <summary>Returned the hex code associated with this name(e.g.</summary>
  802. /// <remarks>Returned the hex code associated with this name(e.g. 0x20 is for the file service)
  803. /// </remarks>
  804. public int GetNameType()
  805. {
  806. return HostName.HexCode;
  807. }
  808. /// <summary>Returns a hashcode for this IP address.</summary>
  809. /// <remarks>
  810. /// Returns a hashcode for this IP address. The hashcode comes from the IP address
  811. /// and is not generated from the string representation. So because NetBIOS nodes
  812. /// can have many names, all names associated with an IP will have the same
  813. /// hashcode.
  814. /// </remarks>
  815. public override int GetHashCode()
  816. {
  817. return Address;
  818. }
  819. /// <summary>Determines if this address is equal two another.</summary>
  820. /// <remarks>
  821. /// Determines if this address is equal two another. Only the IP Addresses
  822. /// are compared. Similar to the
  823. /// <see cref="GetHashCode()">GetHashCode()</see>
  824. /// method, the comparison
  825. /// is based on the integer IP address and not the string representation.
  826. /// </remarks>
  827. public override bool Equals(object obj)
  828. {
  829. return (obj != null) && (obj is NbtAddress) && (((NbtAddress)obj).Address == Address
  830. );
  831. }
  832. /// <summary>
  833. /// Returns the
  834. /// <see cref="string">string</see>
  835. /// representaion of this address.
  836. /// </summary>
  837. public override string ToString()
  838. {
  839. return HostName + "/" + GetHostAddress();
  840. }
  841. }
  842. }