NbtAddress.cs 35 KB

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