NMB.java 7.7 KB

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