001: /* jcifs smb client library in Java
002: * Copyright (C) 2000 "Michael B. Allen" <jcifs at samba dot org>
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package jcifs.netbios;
020:
021: import java.net.InetAddress;
022: import jcifs.util.Hexdump;
023:
024: abstract class NameServicePacket {
025:
026: // opcode
027: static final int QUERY = 0;
028: static final int WACK = 7;
029:
030: // rcode
031: static final int FMT_ERR = 0x1;
032: static final int SRV_ERR = 0x2;
033: static final int IMP_ERR = 0x4;
034: static final int RFS_ERR = 0x5;
035: static final int ACT_ERR = 0x6;
036: static final int CFT_ERR = 0x7;
037:
038: // type/class
039: static final int NB_IN = 0x00200001;
040: static final int NBSTAT_IN = 0x00210001;
041: static final int NB = 0x0020;
042: static final int NBSTAT = 0x0021;
043: static final int IN = 0x0001;
044: static final int A = 0x0001;
045: static final int NS = 0x0002;
046: static final int NULL = 0x000a;
047:
048: static final int HEADER_LENGTH = 12;
049:
050: // header field offsets
051: static final int OPCODE_OFFSET = 2;
052: static final int QUESTION_OFFSET = 4;
053: static final int ANSWER_OFFSET = 6;
054: static final int AUTHORITY_OFFSET = 8;
055: static final int ADDITIONAL_OFFSET = 10;
056:
057: static void writeInt2(int val, byte[] dst, int dstIndex) {
058: dst[dstIndex++] = (byte) ((val >> 8) & 0xFF);
059: dst[dstIndex] = (byte) (val & 0xFF);
060: }
061:
062: static void writeInt4(int val, byte[] dst, int dstIndex) {
063: dst[dstIndex++] = (byte) ((val >> 24) & 0xFF);
064: dst[dstIndex++] = (byte) ((val >> 16) & 0xFF);
065: dst[dstIndex++] = (byte) ((val >> 8) & 0xFF);
066: dst[dstIndex] = (byte) (val & 0xFF);
067: }
068:
069: static int readInt2(byte[] src, int srcIndex) {
070: return ((src[srcIndex] & 0xFF) << 8)
071: + (src[srcIndex + 1] & 0xFF);
072: }
073:
074: static int readInt4(byte[] src, int srcIndex) {
075: return ((src[srcIndex] & 0xFF) << 24)
076: + ((src[srcIndex + 1] & 0xFF) << 16)
077: + ((src[srcIndex + 2] & 0xFF) << 8)
078: + (src[srcIndex + 3] & 0xFF);
079: }
080:
081: static int readNameTrnId(byte[] src, int srcIndex) {
082: return readInt2(src, srcIndex);
083: }
084:
085: int addrIndex;
086: NbtAddress[] addrEntry;
087:
088: int nameTrnId;
089:
090: int opCode, resultCode, questionCount, answerCount, authorityCount,
091: additionalCount;
092: boolean received, isResponse, isAuthAnswer, isTruncated,
093: isRecurDesired, isRecurAvailable, isBroadcast;
094:
095: Name questionName;
096: Name recordName;
097:
098: int questionType, questionClass, recordType, recordClass, ttl,
099: rDataLength;
100:
101: InetAddress addr;
102:
103: NameServicePacket() {
104: isRecurDesired = true;
105: isBroadcast = true;
106: questionCount = 1;
107: questionClass = IN;
108: }
109:
110: int writeWireFormat(byte[] dst, int dstIndex) {
111: int start = dstIndex;
112: dstIndex += writeHeaderWireFormat(dst, dstIndex);
113: dstIndex += writeBodyWireFormat(dst, dstIndex);
114: return dstIndex - start;
115: }
116:
117: int readWireFormat(byte[] src, int srcIndex) {
118: int start = srcIndex;
119: srcIndex += readHeaderWireFormat(src, srcIndex);
120: srcIndex += readBodyWireFormat(src, srcIndex);
121: return srcIndex - start;
122: }
123:
124: int writeHeaderWireFormat(byte[] dst, int dstIndex) {
125: int start = dstIndex;
126: writeInt2(nameTrnId, dst, dstIndex);
127: dst[dstIndex + OPCODE_OFFSET] = (byte) ((isResponse ? 0x80
128: : 0x00)
129: + ((opCode << 3) & 0x78)
130: + (isAuthAnswer ? 0x04 : 0x00)
131: + (isTruncated ? 0x02 : 0x00) + (isRecurDesired ? 0x01
132: : 0x00));
133: dst[dstIndex + OPCODE_OFFSET + 1] = (byte) ((isRecurAvailable ? 0x80
134: : 0x00)
135: + (isBroadcast ? 0x10 : 0x00) + (resultCode & 0x0F));
136: writeInt2(questionCount, dst, start + QUESTION_OFFSET);
137: writeInt2(answerCount, dst, start + ANSWER_OFFSET);
138: writeInt2(authorityCount, dst, start + AUTHORITY_OFFSET);
139: writeInt2(additionalCount, dst, start + ADDITIONAL_OFFSET);
140: return HEADER_LENGTH;
141: }
142:
143: int readHeaderWireFormat(byte[] src, int srcIndex) {
144: nameTrnId = readInt2(src, srcIndex);
145: isResponse = ((src[srcIndex + OPCODE_OFFSET] & 0x80) == 0) ? false
146: : true;
147: opCode = (src[srcIndex + OPCODE_OFFSET] & 0x78) >> 3;
148: isAuthAnswer = ((src[srcIndex + OPCODE_OFFSET] & 0x04) == 0) ? false
149: : true;
150: isTruncated = ((src[srcIndex + OPCODE_OFFSET] & 0x02) == 0) ? false
151: : true;
152: isRecurDesired = ((src[srcIndex + OPCODE_OFFSET] & 0x01) == 0) ? false
153: : true;
154: isRecurAvailable = ((src[srcIndex + OPCODE_OFFSET + 1] & 0x80) == 0) ? false
155: : true;
156: isBroadcast = ((src[srcIndex + OPCODE_OFFSET + 1] & 0x10) == 0) ? false
157: : true;
158: resultCode = src[srcIndex + OPCODE_OFFSET + 1] & 0x0F;
159: questionCount = readInt2(src, srcIndex + QUESTION_OFFSET);
160: answerCount = readInt2(src, srcIndex + ANSWER_OFFSET);
161: authorityCount = readInt2(src, srcIndex + AUTHORITY_OFFSET);
162: additionalCount = readInt2(src, srcIndex + ADDITIONAL_OFFSET);
163: return HEADER_LENGTH;
164: }
165:
166: int writeQuestionSectionWireFormat(byte[] dst, int dstIndex) {
167: int start = dstIndex;
168: dstIndex += questionName.writeWireFormat(dst, dstIndex);
169: writeInt2(questionType, dst, dstIndex);
170: dstIndex += 2;
171: writeInt2(questionClass, dst, dstIndex);
172: dstIndex += 2;
173: return dstIndex - start;
174: }
175:
176: int readQuestionSectionWireFormat(byte[] src, int srcIndex) {
177: int start = srcIndex;
178: srcIndex += questionName.readWireFormat(src, srcIndex);
179: questionType = readInt2(src, srcIndex);
180: srcIndex += 2;
181: questionClass = readInt2(src, srcIndex);
182: srcIndex += 2;
183: return srcIndex - start;
184: }
185:
186: int writeResourceRecordWireFormat(byte[] dst, int dstIndex) {
187: int start = dstIndex;
188: if (recordName == questionName) {
189: dst[dstIndex++] = (byte) 0xC0; // label string pointer to
190: dst[dstIndex++] = (byte) 0x0C; // questionName (offset 12)
191: } else {
192: dstIndex += recordName.writeWireFormat(dst, dstIndex);
193: }
194: writeInt2(recordType, dst, dstIndex);
195: dstIndex += 2;
196: writeInt2(recordClass, dst, dstIndex);
197: dstIndex += 2;
198: writeInt4(ttl, dst, dstIndex);
199: dstIndex += 4;
200: rDataLength = writeRDataWireFormat(dst, dstIndex + 2);
201: writeInt2(rDataLength, dst, dstIndex);
202: dstIndex += 2 + rDataLength;
203: return dstIndex - start;
204: }
205:
206: int readResourceRecordWireFormat(byte[] src, int srcIndex) {
207: int start = srcIndex;
208: int end;
209:
210: if ((src[srcIndex] & 0xC0) == 0xC0) {
211: recordName = questionName; // label string pointer to questionName
212: srcIndex += 2;
213: } else {
214: srcIndex += recordName.readWireFormat(src, srcIndex);
215: }
216: recordType = readInt2(src, srcIndex);
217: srcIndex += 2;
218: recordClass = readInt2(src, srcIndex);
219: srcIndex += 2;
220: ttl = readInt4(src, srcIndex);
221: srcIndex += 4;
222: rDataLength = readInt2(src, srcIndex);
223: srcIndex += 2;
224:
225: addrEntry = new NbtAddress[rDataLength / 6];
226: end = srcIndex + rDataLength;
227: for (addrIndex = 0; srcIndex < end; addrIndex++) {
228: srcIndex += readRDataWireFormat(src, srcIndex);
229: }
230:
231: return srcIndex - start;
232: }
233:
234: abstract int writeBodyWireFormat(byte[] dst, int dstIndex);
235:
236: abstract int readBodyWireFormat(byte[] src, int srcIndex);
237:
238: abstract int writeRDataWireFormat(byte[] dst, int dstIndex);
239:
240: abstract int readRDataWireFormat(byte[] src, int srcIndex);
241:
242: public String toString() {
243: String opCodeString, resultCodeString, questionTypeString, questionClassString, recordTypeString, recordClassString;
244:
245: switch (opCode) {
246: case QUERY:
247: opCodeString = "QUERY";
248: break;
249: case WACK:
250: opCodeString = "WACK";
251: break;
252: default:
253: opCodeString = Integer.toString(opCode);
254: }
255: switch (resultCode) {
256: case FMT_ERR:
257: resultCodeString = "FMT_ERR";
258: break;
259: case SRV_ERR:
260: resultCodeString = "SRV_ERR";
261: break;
262: case IMP_ERR:
263: resultCodeString = "IMP_ERR";
264: break;
265: case RFS_ERR:
266: resultCodeString = "RFS_ERR";
267: break;
268: case ACT_ERR:
269: resultCodeString = "ACT_ERR";
270: break;
271: case CFT_ERR:
272: resultCodeString = "CFT_ERR";
273: break;
274: default:
275: resultCodeString = "0x"
276: + Hexdump.toHexString(resultCode, 1);
277: }
278: switch (questionType) {
279: case NB:
280: questionTypeString = "NB";
281: case NBSTAT:
282: questionTypeString = "NBSTAT";
283: default:
284: questionTypeString = "0x"
285: + Hexdump.toHexString(questionType, 4);
286: }
287: switch (recordType) {
288: case A:
289: recordTypeString = "A";
290: break;
291: case NS:
292: recordTypeString = "NS";
293: break;
294: case NULL:
295: recordTypeString = "NULL";
296: break;
297: case NB:
298: recordTypeString = "NB";
299: case NBSTAT:
300: recordTypeString = "NBSTAT";
301: default:
302: recordTypeString = "0x"
303: + Hexdump.toHexString(recordType, 4);
304: }
305:
306: return new String("nameTrnId="
307: + nameTrnId
308: + ",isResponse="
309: + isResponse
310: + ",opCode="
311: + opCodeString
312: + ",isAuthAnswer="
313: + isAuthAnswer
314: + ",isTruncated="
315: + isTruncated
316: + ",isRecurAvailable="
317: + isRecurAvailable
318: + ",isRecurDesired="
319: + isRecurDesired
320: + ",isBroadcast="
321: + isBroadcast
322: + ",resultCode="
323: + resultCode
324: + ",questionCount="
325: + questionCount
326: + ",answerCount="
327: + answerCount
328: + ",authorityCount="
329: + authorityCount
330: + ",additionalCount="
331: + additionalCount
332: + ",questionName="
333: + questionName
334: + ",questionType="
335: + questionTypeString
336: + ",questionClass="
337: + (questionClass == IN ? "IN" : "0x"
338: + Hexdump.toHexString(questionClass, 4))
339: + ",recordName="
340: + recordName
341: + ",recordType="
342: + recordTypeString
343: + ",recordClass="
344: + (recordClass == IN ? "IN" : "0x"
345: + Hexdump.toHexString(recordClass, 4))
346: + ",ttl=" + ttl + ",rDataLength=" + rDataLength);
347: }
348: }
|