NetBIOSDatagram.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. /*
  2. * Copyright (C) 2006-2010 Alfresco Software Limited.
  3. *
  4. * This file is part of Alfresco
  5. *
  6. * Alfresco is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Alfresco is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package org.alfresco.jlan.netbios;
  20. import java.io.IOException;
  21. import java.net.DatagramPacket;
  22. import java.net.DatagramSocket;
  23. import java.net.InetAddress;
  24. import java.net.UnknownHostException;
  25. import org.alfresco.jlan.util.DataPacker;
  26. /**
  27. * NetBIOS datagram class
  28. *
  29. * <p>Used for sending/receiving NetBIOS broadcast datagrams that are used for name lookups and registration.
  30. *
  31. * @author gkspencer
  32. */
  33. public class NetBIOSDatagram {
  34. // Datagram types
  35. public static final int DIRECT_UNIQUE = 0x10;
  36. public static final int DIRECT_GROUP = 0x11;
  37. public static final int BROADCAST = 0x12;
  38. public static final int DATAGRAM_ERROR = 0x13;
  39. public static final int DATAGRAM_QUERY = 0x14;
  40. public static final int POSITIVE_RESP = 0x15;
  41. public static final int NEGATIVE_RESP = 0x16;
  42. // Datagram flags
  43. public static final int FLG_MOREFRAGMENTS = 0x01;
  44. public static final int FLG_FIRSTPKT = 0x02;
  45. // Default NetBIOS packet buffer size to allocate
  46. public static final int DEFBUFSIZE = 4096;
  47. // NetBIOS datagram offsets
  48. public static final int NB_MSGTYPE = 0;
  49. public static final int NB_FLAGS = 1;
  50. public static final int NB_DATAGRAMID = 2;
  51. public static final int NB_SOURCEIP = 4;
  52. public static final int NB_SOURCEPORT = 8;
  53. public static final int NB_DATAGRAMLEN = 10;
  54. public static final int NB_PKTOFFSET = 12;
  55. public static final int NB_FROMNAME = 14;
  56. public static final int NB_TONAME = 48;
  57. public static final int NB_USERDATA = 82;
  58. public static final int NB_MINLENGTH = 82;
  59. public static final int NB_MINSMBLEN = 100;
  60. // NetBIOS packet buffer
  61. protected byte[] m_buf;
  62. // Next available datagram id
  63. private static int m_nextId;
  64. /**
  65. * NetBIOS Datagram constructor
  66. */
  67. public NetBIOSDatagram() {
  68. // Allocaet a NetBIOS packet buffer
  69. m_buf = new byte [ DEFBUFSIZE];
  70. }
  71. /**
  72. * Create a new NetBIOS datagram using the specified packet buffer.
  73. *
  74. * @param pkt byte[]
  75. */
  76. public NetBIOSDatagram ( byte[] pkt) {
  77. m_buf = pkt;
  78. }
  79. /**
  80. * Create a new NetBIOS datagram with the specified buffer size.
  81. *
  82. * @param bufSize int
  83. */
  84. public NetBIOSDatagram ( int bufSize) {
  85. m_buf = new byte [ bufSize];
  86. }
  87. /**
  88. * Return the next available datagram id.
  89. */
  90. public final static synchronized int getNextDatagramId() {
  91. // Update and return the next available datagram id
  92. return m_nextId++;
  93. }
  94. /**
  95. * Return the NetBIOS buffer.
  96. *
  97. * @return byte[]
  98. */
  99. public final byte[] getBuffer() {
  100. return m_buf;
  101. }
  102. /**
  103. * Get the datagram id.
  104. *
  105. * @return int
  106. */
  107. public final int getDatagramId() {
  108. return DataPacker.getIntelShort ( m_buf, NB_DATAGRAMID);
  109. }
  110. /**
  111. * Get the datagram destination name.
  112. *
  113. * @return NetBIOSName
  114. */
  115. public final NetBIOSName getDestinationName() {
  116. // Decode the NetBIOS name to a string
  117. String name = NetBIOSSession.DecodeName ( m_buf, NB_TONAME + 1);
  118. if ( name != null) {
  119. // Convert the name string to a NetBIOS name
  120. NetBIOSName nbName = new NetBIOSName(name.substring(0,14),name.charAt(15),false);
  121. if ( getMessageType() == DIRECT_GROUP)
  122. nbName.setGroup(true);
  123. return nbName;
  124. }
  125. return null;
  126. }
  127. /**
  128. * Return the datagram flags value.
  129. *
  130. * @return int
  131. */
  132. public final int getFlags() {
  133. return m_buf [ NB_FLAGS] & 0xFF;
  134. }
  135. /**
  136. * Return the datagram length.
  137. *
  138. * @return int
  139. */
  140. public final int getLength() {
  141. return DataPacker.getShort ( m_buf, NB_DATAGRAMLEN);
  142. }
  143. /**
  144. * Return the user data length
  145. *
  146. * @return int
  147. */
  148. public final int getDataLength() {
  149. return getLength() - NB_USERDATA;
  150. }
  151. /**
  152. * Get the NetBIOS datagram message type.
  153. *
  154. * @return int
  155. */
  156. public final int getMessageType() {
  157. return m_buf [ NB_MSGTYPE] & 0xFF;
  158. }
  159. /**
  160. * Return the datagram source IP address.
  161. *
  162. * @return byte[]
  163. */
  164. public final byte[] getSourceIPAddress() {
  165. // Allocate a 4 byte array for the IP address
  166. byte[] ipaddr = new byte [ 4];
  167. // Copy the IP address bytes from the datagram
  168. for ( int i = 0; i < 4; i++)
  169. ipaddr [ i] = m_buf [ NB_SOURCEIP + i];
  170. // Return the IP address bytes
  171. return ipaddr;
  172. }
  173. /**
  174. * Return the datagram source IP address, as a string
  175. *
  176. * @return String
  177. */
  178. public final String getSourceAddress() {
  179. // Get the IP address
  180. byte[] addr = getSourceIPAddress();
  181. // Build the IP address string
  182. StringBuffer addrStr = new StringBuffer();
  183. addrStr.append(addr[0]);
  184. addrStr.append(".");
  185. addrStr.append(addr[1]);
  186. addrStr.append(".");
  187. addrStr.append(addr[2]);
  188. addrStr.append(".");
  189. addrStr.append(addr[3]);
  190. return addrStr.toString();
  191. }
  192. /**
  193. * Get the source NetBIOS name.
  194. *
  195. * @return java.lang.String
  196. */
  197. public final NetBIOSName getSourceName() {
  198. // Decode the NetBIOS name string
  199. String name = NetBIOSSession.DecodeName ( m_buf, NB_FROMNAME + 1);
  200. // Convert the name to a NetBIOS name
  201. if ( name != null) {
  202. // Convert the name string to a NetBIOS name
  203. NetBIOSName nbName = new NetBIOSName(name.substring(0,14),name.charAt(15),false);
  204. return nbName;
  205. }
  206. return null;
  207. }
  208. /**
  209. * Get the source port/socket for the datagram.
  210. *
  211. * @return int
  212. */
  213. public final int getSourcePort() {
  214. return DataPacker.getIntelShort ( m_buf, NB_SOURCEPORT);
  215. }
  216. /**
  217. * Check if the user data is an SMB packet
  218. *
  219. * @return boolean
  220. */
  221. public final boolean isSMBData() {
  222. if ( m_buf[NB_USERDATA] == (byte) 0xFF &&
  223. m_buf[NB_USERDATA+1] == (byte) 'S' &&
  224. m_buf[NB_USERDATA+2] == (byte) 'M' &&
  225. m_buf[NB_USERDATA+3] == (byte) 'B' &&
  226. getLength() >= NB_MINSMBLEN)
  227. return true;
  228. return false;
  229. }
  230. /**
  231. * Return the message type as a string
  232. *
  233. * @return String
  234. */
  235. public final String getMessageTypeString() {
  236. // Determine the message type
  237. String typ = null;
  238. switch ( getMessageType()) {
  239. case DIRECT_GROUP:
  240. typ = "DIRECT GROUP";
  241. break;
  242. case DIRECT_UNIQUE:
  243. typ = "DIRECT UNIQUE";
  244. break;
  245. case DATAGRAM_ERROR:
  246. typ = "DATAGRAM ERROR";
  247. break;
  248. case DATAGRAM_QUERY:
  249. typ = "DATAGRAM QUERY";
  250. break;
  251. case BROADCAST:
  252. typ = "BROADCAST";
  253. break;
  254. case POSITIVE_RESP:
  255. typ = "POSITIVE RESP";
  256. break;
  257. case NEGATIVE_RESP:
  258. typ = "NEGATIVE RESP";
  259. break;
  260. default:
  261. typ = "UNKNOWN";
  262. break;
  263. }
  264. // Return the message type string
  265. return typ;
  266. }
  267. /**
  268. * Send a datagram to the specified NetBIOS name using the global NetBIOS datagram socket
  269. *
  270. * @param dgramTyp Datagram type
  271. * @param fromName From NetBIOS name
  272. * @param fromNameType From NetBIOS name type.
  273. * @param toName To NetBIOS name
  274. * @param toNameType To NetBIOS name type.
  275. * @param userData User data buffer
  276. * @param userLen User data length.
  277. * @param userOff Offset of data within user buffer.
  278. * @param addr Address to send to
  279. * @param port Port to send to
  280. * @exception java.io.IOException Error occurred sending datagram
  281. * @exception UnknownHostException Failed to generate the broadcast mask for the network
  282. */
  283. public final void SendDatagram ( int dgramTyp, String fromName, char fromNameType, String toName, char toNameType,
  284. byte[] userData, int userLen, int userOff, InetAddress addr, int port)
  285. throws IOException, UnknownHostException {
  286. // Set the datagram header values
  287. setMessageType ( dgramTyp);
  288. setSourceName ( fromName, fromNameType);
  289. setDestinationName ( toName, toNameType);
  290. setSourcePort ( RFCNetBIOSProtocol.DATAGRAM);
  291. setSourceIPAddress( InetAddress.getLocalHost().getAddress());
  292. setFlags ( FLG_FIRSTPKT);
  293. if ( m_nextId == 0)
  294. m_nextId = ( int) ( System.currentTimeMillis() & 0x7FFF);
  295. setDatagramId( m_nextId++);
  296. // Set the user data and length
  297. setLength ( userLen + NB_USERDATA);
  298. setUserData ( userData, userLen, userOff);
  299. // Use the global NetBIOS datagram socket to sent the broadcast datagram
  300. NetBIOSDatagramSocket nbSocket = NetBIOSDatagramSocket.getInstance();
  301. nbSocket.sendDatagram(this,addr,port);
  302. }
  303. /**
  304. * Send a datagram to the specified NetBIOS name using the global NetBIOS datagram socket
  305. *
  306. * @param dgramTyp Datagram type
  307. * @param fromName From NetBIOS name
  308. * @param fromNameType From NetBIOS name type.
  309. * @param toName To NetBIOS name
  310. * @param toNameType To NetBIOS name type.
  311. * @param userData User data buffer
  312. * @param userLen User data length.
  313. * @param userOff Offset of data within user buffer.
  314. * @exception java.io.IOException Error occurred sending datagram
  315. * @exception UnknownHostException Failed to generate the broadcast mask for the network
  316. */
  317. public final void SendDatagram ( int dgramTyp, String fromName, char fromNameType, String toName, char toNameType,
  318. byte[] userData, int userLen, int userOff)
  319. throws IOException, UnknownHostException {
  320. // Set the datagram header values
  321. setMessageType ( dgramTyp);
  322. setSourceName ( fromName, fromNameType);
  323. setDestinationName ( toName, toNameType);
  324. setSourcePort ( RFCNetBIOSProtocol.DATAGRAM);
  325. setSourceIPAddress( InetAddress.getLocalHost().getAddress());
  326. setFlags ( FLG_FIRSTPKT);
  327. if ( m_nextId == 0)
  328. m_nextId = ( int) ( System.currentTimeMillis() & 0x7FFF);
  329. setDatagramId( m_nextId++);
  330. // Set the user data and length
  331. setLength ( userLen + NB_USERDATA);
  332. setUserData ( userData, userLen, userOff);
  333. // Use the global NetBIOS datagram socket to sent the broadcast datagram
  334. NetBIOSDatagramSocket nbSocket = NetBIOSDatagramSocket.getInstance();
  335. nbSocket.sendBroadcastDatagram(this);
  336. }
  337. /**
  338. * Send a datagram to the specified NetBIOS name using the global NetBIOS datagram socket
  339. *
  340. * @param dgramTyp Datagram type
  341. * @param fromName From NetBIOS name
  342. * @param toName To NetBIOS name
  343. * @param userData User data buffer
  344. * @param userLen User data length.
  345. * @exception java.io.IOException Error occurred sending datagram
  346. * @exception UnknownHostException Failed to generate the broadcast mask for the network
  347. */
  348. public final void SendDatagram ( int dgramTyp, String fromName, String toName, byte[] userData, int userLen)
  349. throws IOException, UnknownHostException {
  350. // Send the datagram from the standard port
  351. SendDatagram (dgramTyp, fromName, NetBIOSName.FileServer, toName, NetBIOSName.FileServer, userData, userLen, 0);
  352. }
  353. /**
  354. * Send a datagram to the specified NetBIOS name using the supplised datagram socket.
  355. *
  356. * @param dgramTyp Datagram type
  357. * @param sock Datagram socket to use to send the datagram packet.
  358. * @param fromName From NetBIOS name
  359. * @param fromNameType From NetBIOS name type.
  360. * @param toName To NetBIOS name
  361. * @param toNameType To NetBIOS name type.
  362. * @param userData User data buffer
  363. * @param userLen User data length.
  364. * @param userOff Offset of data within user buffer.
  365. * @exception java.io.IOException The exception description.
  366. */
  367. public final void SendDatagram ( int dgramTyp, DatagramSocket sock, String fromName, char fromNameType, String toName,
  368. char toNameType, byte[] userData, int userLen, int userOff) throws IOException {
  369. // Set the datagram header values
  370. setMessageType ( dgramTyp);
  371. setSourceName ( fromName, fromNameType);
  372. setDestinationName ( toName, toNameType);
  373. setSourcePort ( RFCNetBIOSProtocol.DATAGRAM);
  374. setSourceIPAddress( InetAddress.getLocalHost().getAddress());
  375. setFlags ( FLG_FIRSTPKT);
  376. if ( m_nextId == 0)
  377. m_nextId = ( int) ( System.currentTimeMillis() & 0x7FFF);
  378. setDatagramId( m_nextId++);
  379. // Set the user data and length
  380. setLength ( userLen + NB_USERDATA);
  381. setUserData ( userData, userLen, userOff);
  382. // Build a broadcast destination address
  383. InetAddress destAddr = InetAddress.getByName ( NetworkSettings.GenerateBroadcastMask( null));
  384. DatagramPacket dgram = new DatagramPacket ( m_buf, userLen + NB_USERDATA, destAddr, RFCNetBIOSProtocol.DATAGRAM);
  385. // Debug
  386. // HexDump.Dump( m_buf, userLen + NB_USERDATA, 0);
  387. // Send the datagram
  388. sock.send( dgram);
  389. }
  390. /**
  391. * Send a datagram to the specified NetBIOS name using the supplied datagram socket.
  392. *
  393. * @param fromName java.lang.String
  394. * @param toName java.lang.String
  395. * @param userData byte[]
  396. * @param userLen int
  397. * @exception java.io.IOException The exception description.
  398. */
  399. public final void SendDatagram ( int dgramTyp, DatagramSocket sock, String fromName, String toName,
  400. byte[] userData, int userLen) throws IOException {
  401. // Send the datagram from the standard port
  402. SendDatagram (dgramTyp, sock, fromName, NetBIOSName.FileServer, toName, NetBIOSName.FileServer, userData, userLen, 0);
  403. }
  404. /**
  405. * Set the datagram id.
  406. *
  407. * @param id int
  408. */
  409. public final void setDatagramId ( int id) {
  410. DataPacker.putIntelShort ( id, m_buf, NB_DATAGRAMID);
  411. }
  412. /**
  413. * Set the datagram destination name.
  414. *
  415. * @param name java.lang.String
  416. */
  417. public final void setDestinationName ( String name) {
  418. setDestinationName ( name, NetBIOSName.FileServer);
  419. }
  420. /**
  421. * Set the datagram destination name.
  422. *
  423. * @param name java.lang.String
  424. */
  425. public final void setDestinationName ( String name, char typ) {
  426. // Convert the name to NetBIOS RFC encoded name
  427. NetBIOSSession.EncodeName ( name, typ, m_buf, NB_TONAME);
  428. }
  429. /**
  430. * Set the datagram flags value.
  431. *
  432. * @param flg int
  433. */
  434. public final void setFlags ( int flg) {
  435. m_buf [ NB_FLAGS] = ( byte) ( flg & 0xFF);
  436. }
  437. /**
  438. * Set the datagram length.
  439. *
  440. * @param len int
  441. */
  442. public final void setLength(int len) {
  443. DataPacker.putShort (( short) len, m_buf, NB_DATAGRAMLEN);
  444. }
  445. /**
  446. * Set the NetBIOS datagram message type.
  447. *
  448. * @param msg int
  449. */
  450. public final void setMessageType(int msg) {
  451. m_buf [ NB_MSGTYPE] = ( byte) ( msg & 0xFF);
  452. }
  453. /**
  454. * Set the source IP address for the datagram.
  455. *
  456. * @param ipaddr byte[]
  457. */
  458. public final void setSourceIPAddress ( byte[] ipaddr) {
  459. // Pack the IP address into the datagram buffer
  460. for ( int i = 0; i < 4; i++)
  461. m_buf [ NB_SOURCEIP + i] = ipaddr [ i];
  462. }
  463. /**
  464. * Set the datagram source NetBIOS name.
  465. *
  466. * @param name java.lang.String
  467. */
  468. public final void setSourceName(String name) {
  469. // Convert the name to NetBIOS RFC encoded name
  470. NetBIOSSession.EncodeName ( name, NetBIOSName.FileServer, m_buf, NB_FROMNAME);
  471. }
  472. /**
  473. * Set the datagram source NetBIOS name.
  474. *
  475. * @param name java.lang.String
  476. */
  477. public final void setSourceName ( String name, char typ) {
  478. // Convert the name to NetBIOS RFC encoded name
  479. NetBIOSSession.EncodeName ( name, typ, m_buf, NB_FROMNAME);
  480. }
  481. /**
  482. * Set the source port/socket for the datagram.
  483. *
  484. * @param port int
  485. */
  486. public final void setSourcePort(int port) {
  487. DataPacker.putShort(( short) port, m_buf, NB_SOURCEPORT);
  488. }
  489. /**
  490. * Set the user data portion of the datagram.
  491. *
  492. * @param buf byte[]
  493. * @param len int
  494. */
  495. public final void setUserData ( byte[] buf, int len) {
  496. // Copy the user data
  497. System.arraycopy( buf, 0, m_buf, NB_USERDATA, len) ;
  498. }
  499. /**
  500. * Set the user data portion of the datagram.
  501. *
  502. * @param buf User data buffer
  503. * @param len Length of user data
  504. * @param off Offset to start of data within buffer.
  505. */
  506. public final void setUserData ( byte[] buf, int len, int off) {
  507. // Copy the user data
  508. System.arraycopy( buf, off, m_buf, NB_USERDATA, len) ;
  509. }
  510. /**
  511. * Common constructor initialization code.
  512. */
  513. protected final void CommonInit() {
  514. }
  515. }