NameServicePacket.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. // This code is derived from jcifs smb client library <jcifs at samba dot org>
  2. // Ported by J. Arturo <webmaster at komodosoft dot net>
  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. using System.Net;
  18. using SharpCifs.Util;
  19. using SharpCifs.Util.Sharpen;
  20. namespace SharpCifs.Netbios
  21. {
  22. internal abstract class NameServicePacket
  23. {
  24. internal const int Query = 0;
  25. internal const int Wack = 7;
  26. internal const int FmtErr = 0x1;
  27. internal const int SrvErr = 0x2;
  28. internal const int ImpErr = 0x4;
  29. internal const int RfsErr = 0x5;
  30. internal const int ActErr = 0x6;
  31. internal const int CftErr = 0x7;
  32. internal const int NbIn = 0x00200001;
  33. internal const int NbstatIn = 0x00210001;
  34. internal const int Nb = 0x0020;
  35. internal const int Nbstat = 0x0021;
  36. internal const int In = 0x0001;
  37. internal const int A = 0x0001;
  38. internal const int Ns = 0x0002;
  39. internal const int Null = 0x000a;
  40. internal const int HeaderLength = 12;
  41. internal const int OpcodeOffset = 2;
  42. internal const int QuestionOffset = 4;
  43. internal const int AnswerOffset = 6;
  44. internal const int AuthorityOffset = 8;
  45. internal const int AdditionalOffset = 10;
  46. // opcode
  47. // rcode
  48. // type/class
  49. // header field offsets
  50. internal static void WriteInt2(int val, byte[] dst, int dstIndex)
  51. {
  52. dst[dstIndex++] = unchecked((byte)((val >> 8) & unchecked(0xFF)));
  53. dst[dstIndex] = unchecked((byte)(val & unchecked(0xFF)));
  54. }
  55. internal static void WriteInt4(int val, byte[] dst, int dstIndex)
  56. {
  57. dst[dstIndex++] = unchecked((byte)((val >> 24) & unchecked(0xFF)));
  58. dst[dstIndex++] = unchecked((byte)((val >> 16) & unchecked(0xFF)));
  59. dst[dstIndex++] = unchecked((byte)((val >> 8) & unchecked(0xFF)));
  60. dst[dstIndex] = unchecked((byte)(val & unchecked(0xFF)));
  61. }
  62. internal static int ReadInt2(byte[] src, int srcIndex)
  63. {
  64. return ((src[srcIndex] & unchecked(0xFF)) << 8) + (src[srcIndex + 1] & unchecked(
  65. 0xFF));
  66. }
  67. internal static int ReadInt4(byte[] src, int srcIndex)
  68. {
  69. return ((src[srcIndex] & unchecked(0xFF)) << 24) + ((src[srcIndex + 1] & unchecked(
  70. 0xFF)) << 16) + ((src[srcIndex + 2] & unchecked(0xFF)) << 8) + (src
  71. [srcIndex + 3] & unchecked(0xFF));
  72. }
  73. internal static int ReadNameTrnId(byte[] src, int srcIndex)
  74. {
  75. return ReadInt2(src, srcIndex);
  76. }
  77. internal int AddrIndex;
  78. internal NbtAddress[] AddrEntry;
  79. internal int NameTrnId;
  80. internal int OpCode;
  81. internal int ResultCode;
  82. internal int QuestionCount;
  83. internal int AnswerCount;
  84. internal int AuthorityCount;
  85. internal int AdditionalCount;
  86. internal bool Received;
  87. internal bool IsResponse;
  88. internal bool IsAuthAnswer;
  89. internal bool IsTruncated;
  90. internal bool IsRecurDesired;
  91. internal bool IsRecurAvailable;
  92. internal bool IsBroadcast;
  93. internal Name QuestionName;
  94. internal Name RecordName;
  95. internal int QuestionType;
  96. internal int QuestionClass;
  97. internal int RecordType;
  98. internal int RecordClass;
  99. internal int Ttl;
  100. internal int RDataLength;
  101. internal IPAddress Addr;
  102. public NameServicePacket()
  103. {
  104. IsRecurDesired = true;
  105. IsBroadcast = true;
  106. QuestionCount = 1;
  107. QuestionClass = In;
  108. }
  109. internal virtual int WriteWireFormat(byte[] dst, int dstIndex)
  110. {
  111. int start = dstIndex;
  112. dstIndex += WriteHeaderWireFormat(dst, dstIndex);
  113. dstIndex += WriteBodyWireFormat(dst, dstIndex);
  114. return dstIndex - start;
  115. }
  116. internal virtual int ReadWireFormat(byte[] src, int srcIndex)
  117. {
  118. int start = srcIndex;
  119. srcIndex += ReadHeaderWireFormat(src, srcIndex);
  120. srcIndex += ReadBodyWireFormat(src, srcIndex);
  121. return srcIndex - start;
  122. }
  123. internal virtual int WriteHeaderWireFormat(byte[] dst, int dstIndex)
  124. {
  125. int start = dstIndex;
  126. WriteInt2(NameTrnId, dst, dstIndex);
  127. dst[dstIndex + OpcodeOffset] = unchecked((byte)((IsResponse ? unchecked(0x80) : unchecked(0x00)) + ((OpCode << 3) & unchecked(0x78)) + (IsAuthAnswer
  128. ? unchecked(0x04) : unchecked(0x00)) + (IsTruncated ? unchecked(0x02) : unchecked(0x00)) + (IsRecurDesired ? unchecked(0x01)
  129. : unchecked(0x00))));
  130. dst[dstIndex + OpcodeOffset + 1] = unchecked((byte)((IsRecurAvailable ? unchecked(
  131. 0x80) : unchecked(0x00)) + (IsBroadcast ? unchecked(0x10) :
  132. unchecked(0x00)) + (ResultCode & unchecked(0x0F))));
  133. WriteInt2(QuestionCount, dst, start + QuestionOffset);
  134. WriteInt2(AnswerCount, dst, start + AnswerOffset);
  135. WriteInt2(AuthorityCount, dst, start + AuthorityOffset);
  136. WriteInt2(AdditionalCount, dst, start + AdditionalOffset);
  137. return HeaderLength;
  138. }
  139. internal virtual int ReadHeaderWireFormat(byte[] src, int srcIndex)
  140. {
  141. NameTrnId = ReadInt2(src, srcIndex);
  142. IsResponse = ((src[srcIndex + OpcodeOffset] & unchecked(0x80)) == 0) ? false
  143. : true;
  144. OpCode = (src[srcIndex + OpcodeOffset] & unchecked(0x78)) >> 3;
  145. IsAuthAnswer = ((src[srcIndex + OpcodeOffset] & unchecked(0x04)) == 0) ?
  146. false : true;
  147. IsTruncated = ((src[srcIndex + OpcodeOffset] & unchecked(0x02)) == 0) ? false
  148. : true;
  149. IsRecurDesired = ((src[srcIndex + OpcodeOffset] & unchecked(0x01)) == 0) ?
  150. false : true;
  151. IsRecurAvailable = ((src[srcIndex + OpcodeOffset + 1] & unchecked(0x80))
  152. == 0) ? false : true;
  153. IsBroadcast = ((src[srcIndex + OpcodeOffset + 1] & unchecked(0x10)) == 0)
  154. ? false : true;
  155. ResultCode = src[srcIndex + OpcodeOffset + 1] & unchecked(0x0F);
  156. QuestionCount = ReadInt2(src, srcIndex + QuestionOffset);
  157. AnswerCount = ReadInt2(src, srcIndex + AnswerOffset);
  158. AuthorityCount = ReadInt2(src, srcIndex + AuthorityOffset);
  159. AdditionalCount = ReadInt2(src, srcIndex + AdditionalOffset);
  160. return HeaderLength;
  161. }
  162. internal virtual int WriteQuestionSectionWireFormat(byte[] dst, int dstIndex)
  163. {
  164. int start = dstIndex;
  165. dstIndex += QuestionName.WriteWireFormat(dst, dstIndex);
  166. WriteInt2(QuestionType, dst, dstIndex);
  167. dstIndex += 2;
  168. WriteInt2(QuestionClass, dst, dstIndex);
  169. dstIndex += 2;
  170. return dstIndex - start;
  171. }
  172. internal virtual int ReadQuestionSectionWireFormat(byte[] src, int srcIndex)
  173. {
  174. int start = srcIndex;
  175. srcIndex += QuestionName.ReadWireFormat(src, srcIndex);
  176. QuestionType = ReadInt2(src, srcIndex);
  177. srcIndex += 2;
  178. QuestionClass = ReadInt2(src, srcIndex);
  179. srcIndex += 2;
  180. return srcIndex - start;
  181. }
  182. internal virtual int WriteResourceRecordWireFormat(byte[] dst, int dstIndex)
  183. {
  184. int start = dstIndex;
  185. if (RecordName == QuestionName)
  186. {
  187. dst[dstIndex++] = unchecked(unchecked(0xC0));
  188. // label string pointer to
  189. dst[dstIndex++] = unchecked(unchecked(0x0C));
  190. }
  191. else
  192. {
  193. // questionName (offset 12)
  194. dstIndex += RecordName.WriteWireFormat(dst, dstIndex);
  195. }
  196. WriteInt2(RecordType, dst, dstIndex);
  197. dstIndex += 2;
  198. WriteInt2(RecordClass, dst, dstIndex);
  199. dstIndex += 2;
  200. WriteInt4(Ttl, dst, dstIndex);
  201. dstIndex += 4;
  202. RDataLength = WriteRDataWireFormat(dst, dstIndex + 2);
  203. WriteInt2(RDataLength, dst, dstIndex);
  204. dstIndex += 2 + RDataLength;
  205. return dstIndex - start;
  206. }
  207. internal virtual int ReadResourceRecordWireFormat(byte[] src, int srcIndex)
  208. {
  209. int start = srcIndex;
  210. int end;
  211. if ((src[srcIndex] & unchecked(0xC0)) == unchecked(0xC0))
  212. {
  213. RecordName = QuestionName;
  214. // label string pointer to questionName
  215. srcIndex += 2;
  216. }
  217. else
  218. {
  219. srcIndex += RecordName.ReadWireFormat(src, srcIndex);
  220. }
  221. RecordType = ReadInt2(src, srcIndex);
  222. srcIndex += 2;
  223. RecordClass = ReadInt2(src, srcIndex);
  224. srcIndex += 2;
  225. Ttl = ReadInt4(src, srcIndex);
  226. srcIndex += 4;
  227. RDataLength = ReadInt2(src, srcIndex);
  228. srcIndex += 2;
  229. AddrEntry = new NbtAddress[RDataLength / 6];
  230. end = srcIndex + RDataLength;
  231. for (AddrIndex = 0; srcIndex < end; AddrIndex++)
  232. {
  233. srcIndex += ReadRDataWireFormat(src, srcIndex);
  234. }
  235. return srcIndex - start;
  236. }
  237. internal abstract int WriteBodyWireFormat(byte[] dst, int dstIndex);
  238. internal abstract int ReadBodyWireFormat(byte[] src, int srcIndex);
  239. internal abstract int WriteRDataWireFormat(byte[] dst, int dstIndex);
  240. internal abstract int ReadRDataWireFormat(byte[] src, int srcIndex);
  241. public override string ToString()
  242. {
  243. string opCodeString;
  244. string resultCodeString;
  245. string questionTypeString;
  246. string recordTypeString;
  247. switch (OpCode)
  248. {
  249. case Query:
  250. {
  251. opCodeString = "QUERY";
  252. break;
  253. }
  254. case Wack:
  255. {
  256. opCodeString = "WACK";
  257. break;
  258. }
  259. default:
  260. {
  261. opCodeString = Extensions.ToString(OpCode);
  262. break;
  263. }
  264. }
  265. switch (ResultCode)
  266. {
  267. case FmtErr:
  268. {
  269. resultCodeString = "FMT_ERR";
  270. break;
  271. }
  272. case SrvErr:
  273. {
  274. resultCodeString = "SRV_ERR";
  275. break;
  276. }
  277. case ImpErr:
  278. {
  279. resultCodeString = "IMP_ERR";
  280. break;
  281. }
  282. case RfsErr:
  283. {
  284. resultCodeString = "RFS_ERR";
  285. break;
  286. }
  287. case ActErr:
  288. {
  289. resultCodeString = "ACT_ERR";
  290. break;
  291. }
  292. case CftErr:
  293. {
  294. resultCodeString = "CFT_ERR";
  295. break;
  296. }
  297. default:
  298. {
  299. resultCodeString = "0x" + Hexdump.ToHexString(ResultCode, 1);
  300. break;
  301. }
  302. }
  303. switch (QuestionType)
  304. {
  305. case Nb:
  306. {
  307. questionTypeString = "NB";
  308. break;
  309. }
  310. case Nbstat:
  311. {
  312. questionTypeString = "NBSTAT";
  313. break;
  314. }
  315. default:
  316. {
  317. questionTypeString = "0x" + Hexdump.ToHexString(QuestionType, 4);
  318. break;
  319. }
  320. }
  321. switch (RecordType)
  322. {
  323. case A:
  324. {
  325. recordTypeString = "A";
  326. break;
  327. }
  328. case Ns:
  329. {
  330. recordTypeString = "NS";
  331. break;
  332. }
  333. case Null:
  334. {
  335. recordTypeString = "NULL";
  336. break;
  337. }
  338. case Nb:
  339. {
  340. recordTypeString = "NB";
  341. break;
  342. }
  343. case Nbstat:
  344. {
  345. recordTypeString = "NBSTAT";
  346. break;
  347. }
  348. default:
  349. {
  350. recordTypeString = "0x" + Hexdump.ToHexString(RecordType, 4);
  351. break;
  352. }
  353. }
  354. return "nameTrnId=" + NameTrnId + ",isResponse=" + IsResponse + ",opCode="
  355. + opCodeString + ",isAuthAnswer=" + IsAuthAnswer + ",isTruncated=" + IsTruncated
  356. + ",isRecurAvailable=" + IsRecurAvailable + ",isRecurDesired=" + IsRecurDesired
  357. + ",isBroadcast=" + IsBroadcast + ",resultCode=" + ResultCode + ",questionCount="
  358. + QuestionCount + ",answerCount=" + AnswerCount + ",authorityCount=" + AuthorityCount
  359. + ",additionalCount=" + AdditionalCount + ",questionName=" + QuestionName + ",questionType="
  360. + questionTypeString + ",questionClass=" + (QuestionClass == In ? "IN" : "0x" +
  361. Hexdump.ToHexString(QuestionClass, 4)) + ",recordName=" + RecordName + ",recordType="
  362. + recordTypeString + ",recordClass=" + (RecordClass == In ? "IN" : "0x" + Hexdump
  363. .ToHexString(RecordClass, 4)) + ",ttl=" + Ttl + ",rDataLength=" + RDataLength;
  364. }
  365. }
  366. }