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