NMB.java 8.4 KB

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