/src/jcifs/netbios/NameServicePacket.java

https://github.com/drheydenreich/jcifs · Java · 337 lines · 289 code · 27 blank · 21 comment · 15 complexity · 5150ba94372aed83aa6794054ec9f4e1 MD5 · raw file

  1. /* jcifs smb client library in Java
  2. * Copyright (C) 2000 "Michael B. Allen" <jcifs at samba dot org>
  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. */
  18. package jcifs.netbios;
  19. import java.net.InetAddress;
  20. import jcifs.util.Hexdump;
  21. abstract class NameServicePacket {
  22. // opcode
  23. static final int QUERY = 0;
  24. static final int WACK = 7;
  25. // rcode
  26. static final int FMT_ERR = 0x1;
  27. static final int SRV_ERR = 0x2;
  28. static final int IMP_ERR = 0x4;
  29. static final int RFS_ERR = 0x5;
  30. static final int ACT_ERR = 0x6;
  31. static final int CFT_ERR = 0x7;
  32. // type/class
  33. static final int NB_IN = 0x00200001;
  34. static final int NBSTAT_IN = 0x00210001;
  35. static final int NB = 0x0020;
  36. static final int NBSTAT = 0x0021;
  37. static final int IN = 0x0001;
  38. static final int A = 0x0001;
  39. static final int NS = 0x0002;
  40. static final int NULL = 0x000a;
  41. static final int HEADER_LENGTH = 12;
  42. // header field offsets
  43. static final int OPCODE_OFFSET = 2;
  44. static final int QUESTION_OFFSET = 4;
  45. static final int ANSWER_OFFSET = 6;
  46. static final int AUTHORITY_OFFSET = 8;
  47. static final int ADDITIONAL_OFFSET = 10;
  48. static void writeInt2( int val, byte[] dst, int dstIndex ) {
  49. dst[dstIndex++] = (byte)(( val >> 8 ) & 0xFF );
  50. dst[dstIndex] = (byte)( val & 0xFF );
  51. }
  52. static void writeInt4( int val, byte[] dst, int dstIndex ) {
  53. dst[dstIndex++] = (byte)(( val >> 24 ) & 0xFF );
  54. dst[dstIndex++] = (byte)(( val >> 16 ) & 0xFF );
  55. dst[dstIndex++] = (byte)(( val >> 8 ) & 0xFF );
  56. dst[dstIndex] = (byte)( val & 0xFF );
  57. }
  58. static int readInt2( byte[] src, int srcIndex ) {
  59. return (( src[srcIndex] & 0xFF ) << 8 ) +
  60. ( src[srcIndex + 1] & 0xFF );
  61. }
  62. static int readInt4( byte[] src, int srcIndex ) {
  63. return (( src[srcIndex] & 0xFF ) << 24 ) +
  64. (( src[srcIndex + 1] & 0xFF ) << 16 ) +
  65. (( src[srcIndex + 2] & 0xFF ) << 8 ) +
  66. ( src[srcIndex + 3] & 0xFF );
  67. }
  68. static int readNameTrnId( byte[] src, int srcIndex ) {
  69. return readInt2( src, srcIndex );
  70. }
  71. int addrIndex;
  72. NbtAddress[] addrEntry;
  73. int nameTrnId;
  74. int opCode,
  75. resultCode,
  76. questionCount,
  77. answerCount,
  78. authorityCount,
  79. additionalCount;
  80. boolean received,
  81. isResponse,
  82. isAuthAnswer,
  83. isTruncated,
  84. isRecurDesired,
  85. isRecurAvailable,
  86. isBroadcast;
  87. Name questionName;
  88. Name recordName;
  89. int questionType,
  90. questionClass,
  91. recordType,
  92. recordClass,
  93. ttl,
  94. rDataLength;
  95. InetAddress addr;
  96. NameServicePacket() {
  97. isRecurDesired = true;
  98. isBroadcast = true;
  99. questionCount = 1;
  100. questionClass = IN;
  101. }
  102. int writeWireFormat( byte[] dst, int dstIndex ) {
  103. int start = dstIndex;
  104. dstIndex += writeHeaderWireFormat( dst, dstIndex );
  105. dstIndex += writeBodyWireFormat( dst, dstIndex );
  106. return dstIndex - start;
  107. }
  108. int readWireFormat( byte[] src, int srcIndex ) {
  109. int start = srcIndex;
  110. srcIndex += readHeaderWireFormat( src, srcIndex );
  111. srcIndex += readBodyWireFormat( src, srcIndex );
  112. return srcIndex - start;
  113. }
  114. int writeHeaderWireFormat( byte[] dst, int dstIndex ) {
  115. int start = dstIndex;
  116. writeInt2( nameTrnId, dst, dstIndex );
  117. dst[dstIndex + OPCODE_OFFSET] = (byte)(( isResponse ? 0x80 : 0x00 ) +
  118. (( opCode << 3 ) & 0x78 ) +
  119. ( isAuthAnswer ? 0x04 : 0x00 ) +
  120. ( isTruncated ? 0x02 : 0x00 ) +
  121. ( isRecurDesired ? 0x01 : 0x00 ));
  122. dst[dstIndex + OPCODE_OFFSET + 1] = (byte)(( isRecurAvailable ? 0x80 : 0x00 ) +
  123. ( isBroadcast ? 0x10 : 0x00 ) +
  124. ( resultCode & 0x0F ));
  125. writeInt2( questionCount, dst, start + QUESTION_OFFSET );
  126. writeInt2( answerCount, dst, start + ANSWER_OFFSET );
  127. writeInt2( authorityCount, dst, start + AUTHORITY_OFFSET );
  128. writeInt2( additionalCount, dst, start + ADDITIONAL_OFFSET );
  129. return HEADER_LENGTH;
  130. }
  131. int readHeaderWireFormat( byte[] src, int srcIndex ) {
  132. nameTrnId = readInt2( src, srcIndex );
  133. isResponse = (( src[srcIndex + OPCODE_OFFSET] & 0x80 ) == 0 ) ? false : true;
  134. opCode = ( src[srcIndex + OPCODE_OFFSET] & 0x78 ) >> 3;
  135. isAuthAnswer = (( src[srcIndex + OPCODE_OFFSET] & 0x04 ) == 0 ) ? false : true;
  136. isTruncated = (( src[srcIndex + OPCODE_OFFSET] & 0x02 ) == 0 ) ? false : true;
  137. isRecurDesired = (( src[srcIndex + OPCODE_OFFSET] & 0x01 ) == 0 ) ? false : true;
  138. isRecurAvailable =
  139. (( src[srcIndex + OPCODE_OFFSET + 1] & 0x80 ) == 0 ) ? false : true;
  140. isBroadcast = (( src[srcIndex + OPCODE_OFFSET + 1] & 0x10 ) == 0 ) ? false : true;
  141. resultCode = src[srcIndex + OPCODE_OFFSET + 1] & 0x0F;
  142. questionCount = readInt2( src, srcIndex + QUESTION_OFFSET );
  143. answerCount = readInt2( src, srcIndex + ANSWER_OFFSET );
  144. authorityCount = readInt2( src, srcIndex + AUTHORITY_OFFSET );
  145. additionalCount = readInt2( src, srcIndex + ADDITIONAL_OFFSET );
  146. return HEADER_LENGTH;
  147. }
  148. int writeQuestionSectionWireFormat( byte[] dst, int dstIndex ) {
  149. int start = dstIndex;
  150. dstIndex += questionName.writeWireFormat( dst, dstIndex );
  151. writeInt2( questionType, dst, dstIndex );
  152. dstIndex += 2;
  153. writeInt2( questionClass, dst, dstIndex );
  154. dstIndex += 2;
  155. return dstIndex - start;
  156. }
  157. int readQuestionSectionWireFormat( byte[] src, int srcIndex ) {
  158. int start = srcIndex;
  159. srcIndex += questionName.readWireFormat( src, srcIndex );
  160. questionType = readInt2( src, srcIndex );
  161. srcIndex += 2;
  162. questionClass = readInt2( src, srcIndex );
  163. srcIndex += 2;
  164. return srcIndex - start;
  165. }
  166. int writeResourceRecordWireFormat( byte[] dst, int dstIndex ) {
  167. int start = dstIndex;
  168. if( recordName == questionName ) {
  169. dst[dstIndex++] = (byte)0xC0; // label string pointer to
  170. dst[dstIndex++] = (byte)0x0C; // questionName (offset 12)
  171. } else {
  172. dstIndex += recordName.writeWireFormat( dst, dstIndex );
  173. }
  174. writeInt2( recordType, dst, dstIndex );
  175. dstIndex += 2;
  176. writeInt2( recordClass, dst, dstIndex );
  177. dstIndex += 2;
  178. writeInt4( ttl, dst, dstIndex );
  179. dstIndex += 4;
  180. rDataLength = writeRDataWireFormat( dst, dstIndex + 2 );
  181. writeInt2( rDataLength, dst, dstIndex );
  182. dstIndex += 2 + rDataLength;
  183. return dstIndex - start;
  184. }
  185. int readResourceRecordWireFormat( byte[] src, int srcIndex ) {
  186. int start = srcIndex;
  187. int end;
  188. if(( src[srcIndex] & 0xC0 ) == 0xC0 ) {
  189. recordName = questionName; // label string pointer to questionName
  190. srcIndex += 2;
  191. } else {
  192. srcIndex += recordName.readWireFormat( src, srcIndex );
  193. }
  194. recordType = readInt2( src, srcIndex );
  195. srcIndex += 2;
  196. recordClass = readInt2( src, srcIndex );
  197. srcIndex += 2;
  198. ttl = readInt4( src, srcIndex );
  199. srcIndex += 4;
  200. rDataLength = readInt2( src, srcIndex );
  201. srcIndex += 2;
  202. addrEntry = new NbtAddress[rDataLength / 6];
  203. end = srcIndex + rDataLength;
  204. for( addrIndex = 0; srcIndex < end; addrIndex++ ) {
  205. srcIndex += readRDataWireFormat( src, srcIndex );
  206. }
  207. return srcIndex - start;
  208. }
  209. abstract int writeBodyWireFormat( byte[] dst, int dstIndex );
  210. abstract int readBodyWireFormat( byte[] src, int srcIndex );
  211. abstract int writeRDataWireFormat( byte[] dst, int dstIndex );
  212. abstract int readRDataWireFormat( byte[] src, int srcIndex );
  213. public String toString() {
  214. String opCodeString,
  215. resultCodeString,
  216. questionTypeString,
  217. questionClassString,
  218. recordTypeString,
  219. recordClassString;
  220. switch( opCode ) {
  221. case QUERY:
  222. opCodeString = "QUERY";
  223. break;
  224. case WACK:
  225. opCodeString = "WACK";
  226. break;
  227. default:
  228. opCodeString = Integer.toString( opCode );
  229. break;
  230. }
  231. switch( resultCode ) {
  232. case FMT_ERR:
  233. resultCodeString = "FMT_ERR";
  234. break;
  235. case SRV_ERR:
  236. resultCodeString = "SRV_ERR";
  237. break;
  238. case IMP_ERR:
  239. resultCodeString = "IMP_ERR";
  240. break;
  241. case RFS_ERR:
  242. resultCodeString = "RFS_ERR";
  243. break;
  244. case ACT_ERR:
  245. resultCodeString = "ACT_ERR";
  246. break;
  247. case CFT_ERR:
  248. resultCodeString = "CFT_ERR";
  249. break;
  250. default:
  251. resultCodeString = "0x" + Hexdump.toHexString( resultCode, 1 );
  252. break;
  253. }
  254. switch( questionType ) {
  255. case NB:
  256. questionTypeString = "NB";
  257. break;
  258. case NBSTAT:
  259. questionTypeString = "NBSTAT";
  260. break;
  261. default:
  262. questionTypeString = "0x" + Hexdump.toHexString( questionType, 4 );
  263. break;
  264. }
  265. switch( recordType ) {
  266. case A:
  267. recordTypeString = "A";
  268. break;
  269. case NS:
  270. recordTypeString = "NS";
  271. break;
  272. case NULL:
  273. recordTypeString = "NULL";
  274. break;
  275. case NB:
  276. recordTypeString = "NB";
  277. break;
  278. case NBSTAT:
  279. recordTypeString = "NBSTAT";
  280. break;
  281. default:
  282. recordTypeString = "0x" + Hexdump.toHexString( recordType, 4 );
  283. break;
  284. }
  285. return new String(
  286. "nameTrnId=" + nameTrnId +
  287. ",isResponse=" + isResponse +
  288. ",opCode=" + opCodeString +
  289. ",isAuthAnswer=" + isAuthAnswer +
  290. ",isTruncated=" + isTruncated +
  291. ",isRecurAvailable=" + isRecurAvailable +
  292. ",isRecurDesired=" + isRecurDesired +
  293. ",isBroadcast=" + isBroadcast +
  294. ",resultCode=" + resultCode +
  295. ",questionCount=" + questionCount +
  296. ",answerCount=" + answerCount +
  297. ",authorityCount=" + authorityCount +
  298. ",additionalCount=" + additionalCount +
  299. ",questionName=" + questionName +
  300. ",questionType=" + questionTypeString +
  301. ",questionClass=" + ( questionClass == IN ? "IN" :
  302. "0x" + Hexdump.toHexString( questionClass, 4 )) +
  303. ",recordName=" + recordName +
  304. ",recordType=" + recordTypeString +
  305. ",recordClass=" + ( recordClass == IN ? "IN" :
  306. "0x" + Hexdump.toHexString( recordClass, 4 )) +
  307. ",ttl=" + ttl +
  308. ",rDataLength=" + rDataLength );
  309. }
  310. }