NMB.java 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. package de.tudarmstadt.informatik.hostage.protocol.smbutils;
  2. import java.io.IOException;
  3. import java.net.DatagramPacket;
  4. import java.net.DatagramSocket;
  5. import java.net.InetAddress;
  6. import java.net.SocketException;
  7. import java.net.SocketTimeoutException;
  8. import java.net.UnknownHostException;
  9. import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
  10. import de.tudarmstadt.informatik.hostage.net.MyDatagramSocketFactory;
  11. /**
  12. * NetBIOS.
  13. * Used to registrate computers and workgroups in a windows network.
  14. * @author Wulf Pfeiffer
  15. */
  16. public class NMB extends Thread {
  17. private DatagramSocket nbnsSocket;
  18. private DatagramSocket nbdsSocket;
  19. private DatagramPacket packet;
  20. private String ip;
  21. private String[] ipParts;
  22. private InetAddress dst;
  23. private int nbnsPort = 137;
  24. private int nbdsPort = 138;
  25. private String username;
  26. private String workgroup;
  27. private NBNS nbns;
  28. private NBDS nbds;
  29. private boolean isMaster;
  30. private byte[] addr = new byte[4];
  31. private static byte[] transactID = HelperUtils.randomBytes(2);
  32. public NMB(String ip, String username, String workgroup) {
  33. try {
  34. isMaster = false;
  35. this.username = username;
  36. this.workgroup = workgroup;
  37. this.ip = ip;
  38. ipParts = ip.split("\\.");
  39. String newHostAddr = ipParts[0] + "." + ipParts[1] + "." + ipParts[2] + ".255";
  40. dst = InetAddress.getByName(newHostAddr);
  41. addr = addressToBytes(ip);
  42. nbns = new NBNS(addr);
  43. nbds = new NBDS(addr, username, workgroup);
  44. } catch (UnknownHostException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. /**
  49. * Converts an ip address string into a byte array of length 4.
  50. * @param addrString ip address.
  51. * @return 4 byte ip address.
  52. */
  53. private byte[] addressToBytes(String addrString) {
  54. String[] addrParts = addrString.split("\\.");
  55. byte[] newAddr = new byte[4];
  56. newAddr[0] = (byte)Integer.parseInt(addrParts[0]);
  57. newAddr[1] = (byte)Integer.parseInt(addrParts[1]);
  58. newAddr[2] = (byte)Integer.parseInt(addrParts[2]);
  59. newAddr[3] = (byte)Integer.parseInt(addrParts[3]);
  60. return newAddr;
  61. }
  62. /**
  63. * Sends a NBNS packet.
  64. * @param nbns packet.
  65. */
  66. private void sendPacket(NBNS nbns) {
  67. try {
  68. byte[] packetBytes = nbns.getNextPacket();
  69. packet = new DatagramPacket(packetBytes, packetBytes.length, dst, nbnsPort);
  70. nbnsSocket.send(packet);
  71. } catch (IOException e) {
  72. e.printStackTrace();
  73. }
  74. }
  75. /**
  76. * Sends a NBDS packet.
  77. * @param nbds packet.
  78. */
  79. private void sendPacket(NBDS nbds) {
  80. try {
  81. byte[] packetBytes = nbds.getNextPacket();
  82. packet = new DatagramPacket(packetBytes, packetBytes.length, dst, nbdsPort);
  83. nbdsSocket.send(packet);
  84. } catch (IOException e) {
  85. e.printStackTrace();
  86. }
  87. }
  88. /**
  89. * Sends the required packets for user and workgroup registration.
  90. */
  91. private void registrate() {
  92. registrateUser();
  93. registrateGroup();
  94. }
  95. /**
  96. * Sends the required packets for user registration.
  97. */
  98. private void registrateUser() {
  99. nbns.setType(NBNSType.REGISTRATION_UNIQUE);
  100. nbns.setService(NBNSService.SERVER);
  101. nbns.setName(username);
  102. sendPacket(nbns);
  103. nbns.setService(NBNSService.MESSENGER);
  104. sendPacket(nbns);
  105. nbns.setService(NBNSService.WORKSTATION);
  106. sendPacket(nbns);
  107. }
  108. /**
  109. * Sends the required packets for workgroup registration.
  110. */
  111. private void registrateGroup() {
  112. nbns.setName(workgroup);
  113. nbns.setType(NBNSType.REGISTRATION_GROUP);
  114. sendPacket(nbns);
  115. nbns.setService(NBNSService.BROWSER_ELECTION);
  116. sendPacket(nbns);
  117. }
  118. /*
  119. * Sends the browser election request.
  120. */
  121. private void browserElection() {
  122. nbds.setNbdstype(NBDSType.BROWSER);
  123. sendPacket(nbds);
  124. }
  125. /**
  126. * Sends the required packets for MSBROWSE registration.
  127. */
  128. private void registrateMsBrowse() {
  129. nbns.setName("__MSBROWSE__");
  130. nbns.setType(NBNSType.REGISTRATION_MSBROWSE);
  131. nbns.setService(NBNSService.BROWSER);
  132. sendPacket(nbns);
  133. }
  134. /**
  135. * Sends the required packets for local master registration.
  136. */
  137. private void registrateLocalMaster() {
  138. nbns.setName(workgroup);
  139. nbns.setType(NBNSType.REGISTRATION_UNIQUE);
  140. nbns.setService(NBNSService.LOCAL_MASTER_BROWSER);
  141. sendPacket(nbns);
  142. }
  143. /**
  144. * Sends the required packets for host announcement with services.
  145. */
  146. private void announceHost() {
  147. nbds.setNbdstype(NBDSType.HOST_ANNOUNCEMENT_WITH_SERVICES);
  148. sendPacket(nbds);
  149. }
  150. /**
  151. * Sends the required packets for a name query.
  152. */
  153. private void queryName() {
  154. nbns.setType(NBNSType.NAME_QUERY);
  155. nbns.setService(NBNSService.LOCAL_MASTER_BROWSER);
  156. sendPacket(nbns);
  157. }
  158. /**
  159. * Sends the required packets for a request announcement
  160. */
  161. private void requestAnnouncement() {
  162. nbds.setNbdstype(NBDSType.REQUEST_ANNOUNCEMENT);
  163. sendPacket(nbds);
  164. }
  165. /**
  166. * Sends the required packets for a local master announcement to all.
  167. */
  168. private void localMasterAnnouncementAll() {
  169. nbds.setNbdstype(NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL);
  170. sendPacket(nbds);
  171. }
  172. /**
  173. * Sends the required packets for a domain announcement.
  174. */
  175. private void domainAnnouncement() {
  176. nbds.setNbdstype(NBDSType.DOMAIN_ANNOUNCEMENT);
  177. sendPacket(nbds);
  178. }
  179. /**
  180. * Sends the required packets for a local master announcement.
  181. */
  182. private void localMasterAnnouncement() {
  183. nbds.setNbdstype(NBDSType.LOCAL_MASTER_ANNOUNCEMENT);
  184. sendPacket(nbds);
  185. }
  186. @Override
  187. public void run() {
  188. NBSS nbss = new NBSS();
  189. nbss.start();
  190. /*
  191. // XXX: workaround for race condition TODO: FIX FIX FIX
  192. try {
  193. Thread.sleep(1000);
  194. } catch (InterruptedException e) {
  195. e.printStackTrace();
  196. }
  197. */
  198. try {
  199. /*
  200. nbnsSocket = new DatagramSocket(nbnsPort);
  201. nbdsSocket = new DatagramSocket(nbdsPort);
  202. */
  203. MyDatagramSocketFactory factory = new MyDatagramSocketFactory();
  204. nbnsSocket = factory.createDatagramSocket(nbnsPort);
  205. nbdsSocket = factory.createDatagramSocket(nbdsPort);
  206. } catch (SocketException e) {
  207. e.printStackTrace();
  208. } catch (IOException e) {
  209. e.printStackTrace();
  210. }
  211. registrate();
  212. announceHost();
  213. queryName();
  214. checkForAnswers();
  215. if (isMaster) {
  216. registrate();
  217. queryName();
  218. registrate();
  219. queryName();
  220. registrate();
  221. queryName();
  222. browserElection();
  223. browserElection();
  224. browserElection();
  225. browserElection();
  226. registrateMsBrowse();
  227. registrateMsBrowse();
  228. registrateMsBrowse();
  229. registrateMsBrowse();
  230. registrateLocalMaster();
  231. registrateLocalMaster();
  232. registrateLocalMaster();
  233. registrateLocalMaster();
  234. requestAnnouncement();
  235. localMasterAnnouncementAll();
  236. domainAnnouncement();
  237. localMasterAnnouncement();
  238. }
  239. announceHost();
  240. // talk();
  241. nbnsSocket.close();
  242. nbdsSocket.close();
  243. }
  244. private byte[] buffer = new byte[2048];
  245. private boolean masterAnswered = false;
  246. private DatagramPacket receive = new DatagramPacket(buffer, buffer.length);
  247. /**
  248. * Check if the specified workgroup is already existing.
  249. * If someone answers on your register messages there is already a master.
  250. */
  251. private void checkForAnswers() {
  252. try {
  253. nbnsSocket.setSoTimeout(1000);
  254. try {
  255. while (!masterAnswered) {
  256. nbnsSocket.receive(receive);
  257. if (!(receive.getAddress().toString().equals("/"+ip))) {
  258. masterAnswered = true;
  259. isMaster = false;
  260. }
  261. }
  262. } catch (SocketTimeoutException e) {
  263. isMaster = true;
  264. e.printStackTrace();
  265. }
  266. } catch (IOException e) {
  267. isMaster = true;
  268. e.printStackTrace();
  269. }
  270. }
  271. /**
  272. * Returns the current transactID and increases it by one.
  273. * @return transactID.
  274. */
  275. public static byte[] getAndIncTransactID() {
  276. transactID[1]++;
  277. if (transactID[1] == 0x00) {
  278. transactID[0]++;
  279. }
  280. return transactID;
  281. }
  282. /**
  283. * Handling requests after initial registration
  284. */
  285. private void talk() {
  286. try {
  287. nbnsSocket.setSoTimeout(0);
  288. } catch (SocketException e) {
  289. e.printStackTrace();
  290. }
  291. DatagramPacket request = new DatagramPacket(buffer, buffer.length);
  292. DatagramPacket response = new DatagramPacket(buffer, buffer.length);
  293. while (true) {
  294. try {
  295. nbnsSocket.receive(request);
  296. byte[] resp = nbns.getNextResponse(request.getData(), addressToBytes(ip));
  297. response = new DatagramPacket(resp, resp.length, request.getAddress(), nbnsPort);
  298. nbnsSocket.send(response);
  299. } catch (IOException e) {
  300. e.printStackTrace();
  301. }
  302. }
  303. }
  304. }