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