1 18 19 package jcifs.netbios; 20 21 import java.net.InetAddress ; 22 import java.net.DatagramSocket ; 23 import java.net.DatagramPacket ; 24 import java.net.UnknownHostException ; 25 import java.io.IOException ; 26 import java.io.InterruptedIOException ; 27 import java.util.HashMap ; 28 import java.util.StringTokenizer ; 29 import jcifs.Config; 30 import jcifs.util.Hexdump; 31 import jcifs.util.LogStream; 32 33 class NameServiceClient implements Runnable { 34 35 static final int DEFAULT_SO_TIMEOUT = 5000; 36 static final int DEFAULT_RCV_BUF_SIZE = 576; 37 static final int DEFAULT_SND_BUF_SIZE = 576; 38 static final int NAME_SERVICE_UDP_PORT = 137; 39 static final int DEFAULT_RETRY_COUNT = 2; 40 static final int DEFAULT_RETRY_TIMEOUT = 3000; 41 42 static final int RESOLVER_LMHOSTS = 1; 43 static final int RESOLVER_BCAST = 2; 44 static final int RESOLVER_WINS = 3; 45 46 private static final int SND_BUF_SIZE = Config.getInt( "jcifs.netbios.snd_buf_size", DEFAULT_SND_BUF_SIZE ); 47 private static final int RCV_BUF_SIZE = Config.getInt( "jcifs.netbios.rcv_buf_size", DEFAULT_RCV_BUF_SIZE ); 48 private static final int SO_TIMEOUT = Config.getInt( "jcifs.netbios.soTimeout", DEFAULT_SO_TIMEOUT ); 49 private static final int RETRY_COUNT = Config.getInt( "jcifs.netbios.retryCount", DEFAULT_RETRY_COUNT ); 50 private static final int RETRY_TIMEOUT = Config.getInt( "jcifs.netbios.retryTimeout", DEFAULT_RETRY_TIMEOUT); 51 private static final int LPORT = Config.getInt( "jcifs.netbios.lport", 0 ); 52 private static final InetAddress LADDR = Config.getInetAddress( "jcifs.netbios.laddr", null ); 53 private static final String RO = Config.getProperty( "jcifs.resolveOrder" ); 54 55 private static LogStream log = LogStream.getInstance(); 56 57 private final Object LOCK = new Object (); 58 59 private int lport, closeTimeout; 60 private byte[] snd_buf, rcv_buf; 61 private DatagramSocket socket; 62 private DatagramPacket in, out; 63 private HashMap responseTable = new HashMap (); 64 private Thread thread; 65 private int nextNameTrnId = 0; 66 private int[] resolveOrder; 67 68 InetAddress laddr, baddr; 69 70 NameServiceClient() { 71 this( LPORT, LADDR ); 72 } 73 NameServiceClient( int lport, InetAddress laddr ) { 74 this.lport = lport; 75 this.laddr = laddr; 76 77 try { 78 baddr = Config.getInetAddress( "jcifs.netbios.baddr", 79 InetAddress.getByName( "255.255.255.255" )); 80 } catch( UnknownHostException uhe ) { 81 } 82 83 snd_buf = new byte[SND_BUF_SIZE]; 84 rcv_buf = new byte[RCV_BUF_SIZE]; 85 out = new DatagramPacket ( snd_buf, SND_BUF_SIZE, baddr, NAME_SERVICE_UDP_PORT ); 86 in = new DatagramPacket ( rcv_buf, RCV_BUF_SIZE ); 87 88 if( RO == null || RO.length() == 0 ) { 89 90 95 96 if( NbtAddress.getWINSAddress() == null ) { 97 resolveOrder = new int[2]; 98 resolveOrder[0] = RESOLVER_LMHOSTS; 99 resolveOrder[1] = RESOLVER_BCAST; 100 } else { 101 resolveOrder = new int[3]; 102 resolveOrder[0] = RESOLVER_LMHOSTS; 103 resolveOrder[1] = RESOLVER_WINS; 104 resolveOrder[2] = RESOLVER_BCAST; 105 } 106 } else { 107 int[] tmp = new int[3]; 108 StringTokenizer st = new StringTokenizer ( RO, "," ); 109 int i = 0; 110 while( st.hasMoreTokens() ) { 111 String s = st.nextToken().trim(); 112 if( s.equalsIgnoreCase( "LMHOSTS" )) { 113 tmp[i++] = RESOLVER_LMHOSTS; 114 } else if( s.equalsIgnoreCase( "WINS" )) { 115 if( NbtAddress.getWINSAddress() == null ) { 116 if( log.level > 1 ) { 117 log.println( "NetBIOS resolveOrder specifies WINS however the " + 118 "jcifs.netbios.wins property has not been set" ); 119 } 120 continue; 121 } 122 tmp[i++] = RESOLVER_WINS; 123 } else if( s.equalsIgnoreCase( "BCAST" )) { 124 tmp[i++] = RESOLVER_BCAST; 125 } else if( s.equalsIgnoreCase( "DNS" )) { 126 ; } else if( log.level > 1 ) { 128 log.println( "unknown resolver method: " + s ); 129 } 130 } 131 resolveOrder = new int[i]; 132 System.arraycopy( tmp, 0, resolveOrder, 0, i ); 133 } 134 } 135 136 int getNextNameTrnId() { 137 if(( ++nextNameTrnId & 0xFFFF ) == 0 ) { 138 nextNameTrnId = 1; 139 } 140 return nextNameTrnId; 141 } 142 void ensureOpen( int timeout ) throws IOException { 143 closeTimeout = 0; 144 if( SO_TIMEOUT != 0 ) { 145 closeTimeout = Math.max( SO_TIMEOUT, timeout ); 146 } 147 if( socket == null ) { 150 socket = new DatagramSocket ( lport, laddr ); 151 thread = new Thread ( this, "JCIFS-NameServiceClient" ); 152 thread.setDaemon( true ); 153 thread.start(); 154 } 155 } 156 void tryClose() { 157 synchronized( LOCK ) { 158 159 166 167 if( socket != null ) { 168 socket.close(); 169 socket = null; 170 } 171 thread = null; 172 responseTable.clear(); 173 } 174 } 175 public void run() { 176 int nameTrnId; 177 NameServicePacket response; 178 179 try { 180 while( thread == Thread.currentThread() ) { 181 in.setLength( RCV_BUF_SIZE ); 182 183 socket.setSoTimeout( closeTimeout ); 184 socket.receive( in ); 185 186 if( log.level > 3 ) 187 log.println( "NetBIOS: new data read from socket" ); 188 189 nameTrnId = NameServicePacket.readNameTrnId( rcv_buf, 0 ); 190 response = (NameServicePacket)responseTable.get( new Integer ( nameTrnId )); 191 if( response == null || response.received ) { 192 continue; 193 } 194 synchronized( response ) { 195 response.readWireFormat( rcv_buf, 0 ); 196 response.received = true; 197 198 if( log.level > 3 ) { 199 log.println( response ); 200 Hexdump.hexdump( log, rcv_buf, 0, in.getLength() ); 201 } 202 203 response.notify(); 204 } 205 } 206 } catch( Exception ex ) { 207 if( log.level > 2 ) 208 ex.printStackTrace( log ); 209 tryClose(); 210 } 211 } 212 void send( NameServicePacket request, NameServicePacket response, 213 int timeout ) throws IOException { 214 Integer nid = null; 215 int count = 0; 216 217 synchronized( response ) { 218 do { 219 try { 220 synchronized( LOCK ) { 221 request.nameTrnId = getNextNameTrnId(); 222 nid = new Integer ( request.nameTrnId ); 223 224 out.setAddress( request.addr ); 225 out.setLength( request.writeWireFormat( snd_buf, 0 )); 226 response.received = false; 227 228 responseTable.put( nid, response ); 229 ensureOpen( timeout + 1000 ); 230 socket.send( out ); 231 232 if( log.level > 3 ) { 233 log.println( request ); 234 Hexdump.hexdump( log, snd_buf, 0, out.getLength() ); 235 } 236 } 237 238 response.wait( timeout ); 239 240 } catch( InterruptedException ie ) { 241 } finally { 242 responseTable.remove( nid ); 243 } 244 245 if( !response.received && 246 NbtAddress.NBNS.length > 1 && 247 NbtAddress.isWINS( request.addr )) { 248 252 request.addr = NbtAddress.switchWINS(); 253 if( count == 0 ) { 254 count = NbtAddress.NBNS.length - 1; 255 } 256 } 257 } while( count-- > 0 ); 258 } 259 } 260 261 NbtAddress[] getAllByName( Name name, InetAddress addr ) 262 throws UnknownHostException { 263 int n; 264 NameQueryRequest request = new NameQueryRequest( name ); 265 NameQueryResponse response = new NameQueryResponse(); 266 267 request.addr = addr != null ? addr : NbtAddress.getWINSAddress(); 268 request.isBroadcast = request.addr == null; 269 270 if( request.isBroadcast ) { 271 request.addr = baddr; 272 n = RETRY_COUNT; 273 } else { 274 request.isBroadcast = false; 275 n = 1; 276 } 277 278 do { 279 try { 280 send( request, response, RETRY_TIMEOUT ); 281 } catch( IOException ioe ) { 282 if( log.level > 1 ) 283 ioe.printStackTrace( log ); 284 throw new UnknownHostException ( name.name ); 285 } 286 287 if( response.received && response.resultCode == 0 ) { 288 return response.addrEntry; 289 } 290 } while( --n > 0 && request.isBroadcast ); 291 292 throw new UnknownHostException ( name.name ); 293 } 294 NbtAddress getByName( Name name, InetAddress addr ) 295 throws UnknownHostException { 296 int n; 297 NameQueryRequest request = new NameQueryRequest( name ); 298 NameQueryResponse response = new NameQueryResponse(); 299 300 if( addr != null ) { 303 request.addr = addr; 304 request.isBroadcast = (addr.getAddress()[3] == (byte)0xFF); 305 306 n = RETRY_COUNT; 307 do { 308 try { 309 send( request, response, RETRY_TIMEOUT ); 310 } catch( IOException ioe ) { 311 if( log.level > 1 ) 312 ioe.printStackTrace( log ); 313 throw new UnknownHostException ( name.name ); 314 } 315 316 if( response.received && response.resultCode == 0 ) { 317 int last = response.addrEntry.length - 1; 318 response.addrEntry[last].hostName.srcHashCode = addr.hashCode(); 319 return response.addrEntry[last]; 320 } 321 } while( --n > 0 && request.isBroadcast ); 322 323 throw new UnknownHostException ( name.name ); 324 } 325 326 329 330 for( int i = 0; i < resolveOrder.length; i++ ) { 331 try { 332 switch( resolveOrder[i] ) { 333 case RESOLVER_LMHOSTS: 334 NbtAddress ans = Lmhosts.getByName( name ); 335 if( ans != null ) { 336 ans.hostName.srcHashCode = 0; return ans; 339 } 340 break; 341 case RESOLVER_WINS: 342 case RESOLVER_BCAST: 343 if( resolveOrder[i] == RESOLVER_WINS && 344 name.name != NbtAddress.MASTER_BROWSER_NAME && 345 name.hexCode != 0x1d ) { 346 request.addr = NbtAddress.getWINSAddress(); 347 request.isBroadcast = false; 348 } else { 349 request.addr = baddr; 350 request.isBroadcast = true; 351 } 352 353 n = RETRY_COUNT; 354 while( n-- > 0 ) { 355 try { 356 send( request, response, RETRY_TIMEOUT ); 357 } catch( IOException ioe ) { 358 if( log.level > 1 ) 359 ioe.printStackTrace( log ); 360 throw new UnknownHostException ( name.name ); 361 } 362 if( response.received && response.resultCode == 0 ) { 363 364 369 response.addrEntry[0].hostName.srcHashCode = 370 request.addr.hashCode(); 371 return response.addrEntry[0]; 372 } else if( resolveOrder[i] == RESOLVER_WINS ) { 373 375 break; 376 } 377 } 378 break; 379 } 380 } catch( IOException ioe ) { 381 } 382 } 383 throw new UnknownHostException ( name.name ); 384 } 385 NbtAddress[] getNodeStatus( NbtAddress addr ) throws UnknownHostException { 386 int n, srcHashCode; 387 NodeStatusRequest request; 388 NodeStatusResponse response; 389 390 response = new NodeStatusResponse( addr ); 391 request = new NodeStatusRequest( 392 new Name( NbtAddress.ANY_HOSTS_NAME, 0x00, null)); 393 request.addr = addr.getInetAddress(); 394 395 n = RETRY_COUNT; 396 while( n-- > 0 ) { 397 try { 398 send( request, response, RETRY_TIMEOUT ); 399 } catch( IOException ioe ) { 400 if( log.level > 1 ) 401 ioe.printStackTrace( log ); 402 throw new UnknownHostException ( addr.toString() ); 403 } 404 if( response.received && response.resultCode == 0 ) { 405 406 418 419 srcHashCode = request.addr.hashCode(); 420 for( int i = 0; i < response.addressArray.length; i++ ) { 421 response.addressArray[i].hostName.srcHashCode = srcHashCode; 422 } 423 return response.addressArray; 424 } 425 } 426 throw new UnknownHostException ( addr.hostName.name ); 427 } 428 } 429 | Popular Tags |