1 18 19 package com.knowgate.jcifs.netbios; 20 21 import java.net.InetAddress ; 22 import java.net.UnknownHostException ; 23 import java.net.SocketException ; 24 import java.io.IOException ; 25 import java.io.UnsupportedEncodingException ; 26 import java.util.HashMap ; 27 28 import com.knowgate.jcifs.Config; 29 30 import com.knowgate.misc.Gadgets; 31 32 81 82 public final class NbtAddress { 83 84 88 89 static final String ANY_HOSTS_NAME = "*\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"; 90 91 95 96 public static final String MASTER_BROWSER_NAME = "\u0001\u0002__MSBROWSE__\u0002"; 97 98 102 103 public static final String SMBSERVER_NAME = "*SMBSERVER "; 104 105 109 110 public static final int B_NODE = 0; 111 112 117 118 public static final int P_NODE = 1; 119 120 124 125 public static final int M_NODE = 2; 126 127 132 133 public static final int H_NODE = 3; 134 135 static final InetAddress [] NBNS = Config.getInetAddressArray( "jcifs.netbios.wins", ",", new InetAddress [0] ); 136 137 141 142 private static final NameServiceClient CLIENT = new NameServiceClient(); 143 144 private static final int DEFAULT_CACHE_POLICY = 30; 145 private static final int CACHE_POLICY = Config.getInt( "jcifs.netbios.cachePolicy", DEFAULT_CACHE_POLICY ); 146 private static final int FOREVER = -1; 147 private static int nbnsIndex = 0; 148 149 private static final HashMap ADDRESS_CACHE = new HashMap (); 150 private static final HashMap LOOKUP_TABLE = new HashMap (); 151 152 static final Name UNKNOWN_NAME = new Name( "0.0.0.0", 0x00, null ); 153 static final NbtAddress UNKNOWN_ADDRESS = new NbtAddress( UNKNOWN_NAME, 0, false, B_NODE ); 154 static final byte[] UNKNOWN_MAC_ADDRESS = new byte[] { 155 (byte)0x00, (byte)0x00, (byte)0x00, 156 (byte)0x00, (byte)0x00, (byte)0x00 157 }; 158 159 static final class CacheEntry { 160 Name hostName; 161 NbtAddress address; 162 long expiration; 163 164 CacheEntry( Name hostName, NbtAddress address, long expiration ) { 165 this.hostName = hostName; 166 this.address = address; 167 this.expiration = expiration; 168 } 169 } 170 171 static NbtAddress localhost; 172 173 static { 174 InetAddress localInetAddress; 175 String localHostname; 176 Name localName; 177 178 180 181 ADDRESS_CACHE.put( UNKNOWN_NAME, new CacheEntry( UNKNOWN_NAME, UNKNOWN_ADDRESS, FOREVER )); 182 183 186 localInetAddress = CLIENT.laddr; 187 if( localInetAddress == null ) { 188 try { 189 localInetAddress = InetAddress.getLocalHost(); 190 } catch( UnknownHostException uhe ) { 191 } 192 } 193 194 199 localHostname = Config.getProperty( "jcifs.netbios.hostname", null ); 200 if( localHostname == null || localHostname.length() == 0 ) { 201 byte[] addr = localInetAddress.getAddress(); 202 localHostname = "JCIFS" + 203 ( addr[2] & 0xFF ) + "_" + 204 ( addr[3] & 0xFF ) + "_" + 205 Gadgets.toHexString( (int)( Math.random() * (double)0xFF ), 2 ); 206 } 207 208 212 localName = new Name( localHostname, 0x00, 213 Config.getProperty( "jcifs.netbios.scope", null )); 214 localhost = new NbtAddress( localName, 215 localInetAddress.hashCode(), 216 false, 217 B_NODE, 218 false, false, true, false, 219 UNKNOWN_MAC_ADDRESS ); 220 cacheAddress( localName, localhost, FOREVER ); 221 } 222 223 static void cacheAddress( Name hostName, NbtAddress addr ) { 224 if( CACHE_POLICY == 0 ) { 225 return; 226 } 227 long expiration = -1; 228 if( CACHE_POLICY != FOREVER ) { 229 expiration = System.currentTimeMillis() + CACHE_POLICY * 1000; 230 } 231 cacheAddress( hostName, addr, expiration ); 232 } 233 static void cacheAddress( Name hostName, NbtAddress addr, long expiration ) { 234 if( CACHE_POLICY == 0 ) { 235 return; 236 } 237 synchronized( ADDRESS_CACHE ) { 238 CacheEntry entry = (CacheEntry)ADDRESS_CACHE.get( hostName ); 239 if( entry == null ) { 240 entry = new CacheEntry( hostName, addr, expiration ); 241 ADDRESS_CACHE.put( hostName, entry ); 242 } else { 243 entry.address = addr; 244 entry.expiration = expiration; 245 } 246 } 247 } 248 static void cacheAddressArray( NbtAddress[] addrs ) { 249 if( CACHE_POLICY == 0 ) { 250 return; 251 } 252 long expiration = -1; 253 if( CACHE_POLICY != FOREVER ) { 254 expiration = System.currentTimeMillis() + CACHE_POLICY * 1000; 255 } 256 synchronized( ADDRESS_CACHE ) { 257 for( int i = 0; i < addrs.length; i++ ) { 258 CacheEntry entry = (CacheEntry)ADDRESS_CACHE.get( addrs[i].hostName ); 259 if( entry == null ) { 260 entry = new CacheEntry( addrs[i].hostName, addrs[i], expiration ); 261 ADDRESS_CACHE.put( addrs[i].hostName, entry ); 262 } else { 263 entry.address = addrs[i]; 264 entry.expiration = expiration; 265 } 266 } 267 } 268 } 269 static NbtAddress getCachedAddress( Name hostName ) { 270 if( CACHE_POLICY == 0 ) { 271 return null; 272 } 273 synchronized( ADDRESS_CACHE ) { 274 CacheEntry entry = (CacheEntry)ADDRESS_CACHE.get( hostName ); 275 if( entry != null && entry.expiration < System.currentTimeMillis() && 276 entry.expiration >= 0 ) { 277 entry = null; 278 } 279 return entry != null ? entry.address : null; 280 } 281 } 282 283 static NbtAddress doNameQuery( Name name, InetAddress svr ) 284 throws UnknownHostException { 285 NbtAddress addr; 286 287 if( name.hexCode == 0x1d && svr == null ) { 288 svr = CLIENT.baddr; } 290 name.srcHashCode = svr != null ? svr.hashCode() : 0; 291 addr = getCachedAddress( name ); 292 293 if( addr == null ) { 294 298 if(( addr = (NbtAddress)checkLookupTable( name )) == null ) { 299 try { 300 addr = CLIENT.getByName( name, svr ); 301 } catch( UnknownHostException uhe ) { 302 addr = UNKNOWN_ADDRESS; 303 } finally { 304 cacheAddress( name, addr ); 305 updateLookupTable( name ); 306 } 307 } 308 } 309 if( addr == UNKNOWN_ADDRESS ) { 310 throw new UnknownHostException ( name.toString() ); 311 } 312 return addr; 313 } 314 315 private static Object checkLookupTable( Name name ) { 316 Object obj; 317 318 synchronized( LOOKUP_TABLE ) { 319 if( LOOKUP_TABLE.containsKey( name ) == false ) { 320 LOOKUP_TABLE.put( name, name ); 321 return null; 322 } 323 while( LOOKUP_TABLE.containsKey( name )) { 324 try { 325 LOOKUP_TABLE.wait(); 326 } catch( InterruptedException e ) { 327 } 328 } 329 } 330 obj = getCachedAddress( name ); 331 if( obj == null ) { 332 synchronized( LOOKUP_TABLE ) { 333 LOOKUP_TABLE.put( name, name ); 334 } 335 } 336 337 return obj; 338 } 339 private static void updateLookupTable( Name name ) { 340 synchronized( LOOKUP_TABLE ) { 341 LOOKUP_TABLE.remove( name ); 342 LOOKUP_TABLE.notifyAll(); 343 } 344 } 345 346 352 353 public static NbtAddress getLocalHost() throws UnknownHostException { 354 return localhost; 355 } 356 357 366 367 public static NbtAddress getByName( String host ) 368 throws UnknownHostException { 369 return getByName( host, 0x00, null ); 370 } 371 372 387 388 public static NbtAddress getByName( String host, 389 int type, 390 String scope ) 391 throws UnknownHostException { 392 393 return getByName( host, type, scope, null ); 394 } 395 396 401 402 public static NbtAddress getByName( String host, 403 int type, 404 String scope, 405 InetAddress svr ) 406 throws UnknownHostException { 407 408 if( host == null || host.length() == 0 ) { 409 return getLocalHost(); 410 } 411 if( !Character.isDigit( host.charAt(0) )) { 412 return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr ); 413 } else { 414 int IP = 0x00; 415 int hitDots = 0; 416 char[] data = host.toCharArray(); 417 418 for( int i = 0; i < data.length; i++ ) { 419 char c = data[i]; 420 if( c < 48 || c > 57 ) { 421 return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr ); 422 } 423 int b = 0x00; 424 while( c != '.' ) { 425 if( c < 48 || c > 57 ) { 426 return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr ); 427 } 428 b = b * 10 + c - '0'; 429 430 if( ++i >= data.length ) 431 break; 432 433 c = data[i]; 434 } 435 if( b > 0xFF ) { 436 return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr ); 437 } 438 IP = ( IP << 8 ) + b; 439 hitDots++; 440 } 441 if( hitDots != 4 || host.endsWith( "." )) { 442 return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr ); 443 } 444 return new NbtAddress( UNKNOWN_NAME, IP, false, B_NODE ); 445 } 446 } 447 448 457 458 459 public static NbtAddress[] getAllByAddress( String host ) 460 throws UnknownHostException { 461 return getAllByAddress( getByName( host, 0x00, null )); 462 } 463 464 465 478 479 480 public static NbtAddress[] getAllByAddress( String host, 481 int type, 482 String scope ) 483 throws UnknownHostException { 484 return getAllByAddress( getByName( host, type, scope )); 485 } 486 487 488 497 498 public static NbtAddress[] getAllByAddress( NbtAddress addr ) 499 throws UnknownHostException { 500 try { 501 NbtAddress[] addrs = CLIENT.getNodeStatus( addr ); 502 cacheAddressArray( addrs ); 503 return addrs; 504 } catch( UnknownHostException uhe ) { 505 throw new UnknownHostException ( "no name with type 0x" + 506 Gadgets.toHexString( addr.hostName.hexCode, 2 ) + 507 ((( addr.hostName.scope == null ) || 508 ( addr.hostName.scope.length() == 0 )) ? 509 " with no scope" : " with scope " + addr.hostName.scope ) + 510 " for host " + addr.getHostAddress() ); 511 } 512 } 513 514 public static InetAddress getWINSAddress() { 515 return NBNS.length == 0 ? null : NBNS[nbnsIndex]; 516 } 517 public static boolean isWINS( InetAddress svr ) { 518 for( int i = 0; svr != null && i < NBNS.length; i++ ) { 519 if( svr.hashCode() == NBNS[i].hashCode() ) { 520 return true; 521 } 522 } 523 return false; 524 } 525 static InetAddress switchWINS() { 526 nbnsIndex = (nbnsIndex + 1) < NBNS.length ? nbnsIndex + 1 : 0; 527 return NBNS.length == 0 ? null : NBNS[nbnsIndex]; 528 } 529 530 Name hostName; 531 int address, nodeType; 532 boolean groupName, 533 isBeingDeleted, 534 isInConflict, 535 isActive, 536 isPermanent, 537 isDataFromNodeStatus; 538 byte[] macAddress; 539 String calledName; 540 541 NbtAddress( Name hostName, int address, boolean groupName, int nodeType ) { 542 this.hostName = hostName; 543 this.address = address; 544 this.groupName = groupName; 545 this.nodeType = nodeType; 546 } 547 548 NbtAddress( Name hostName, 549 int address, 550 boolean groupName, 551 int nodeType, 552 boolean isBeingDeleted, 553 boolean isInConflict, 554 boolean isActive, 555 boolean isPermanent, 556 byte[] macAddress ) { 557 558 562 this.hostName = hostName; 563 this.address = address; 564 this.groupName = groupName; 565 this.nodeType = nodeType; 566 this.isBeingDeleted = isBeingDeleted; 567 this.isInConflict = isInConflict; 568 this.isActive = isActive; 569 this.isPermanent = isPermanent; 570 this.macAddress = macAddress; 571 isDataFromNodeStatus = true; 572 } 573 574 577 578 public String firstCalledName() { 579 580 calledName = hostName.name; 581 582 if( Character.isDigit( calledName.charAt( 0 ))) { 583 int i, len, dots; 584 char[] data; 585 586 i = dots = 0; 587 len = calledName.length(); 588 data = calledName.toCharArray(); 589 while( i < len && Character.isDigit( data[i++] )) { 590 if( i == len && dots == 3 ) { 591 calledName = SMBSERVER_NAME; 593 break; 594 } 595 if( i < len && data[i] == '.' ) { 596 dots++; 597 i++; 598 } 599 } 600 } else if( hostName.hexCode == 0x1D ) { 601 calledName = SMBSERVER_NAME; 602 } 603 604 return calledName; 605 } 606 public String nextCalledName() { 607 608 if( calledName == hostName.name ) { 609 calledName = SMBSERVER_NAME; 610 } else if( calledName == SMBSERVER_NAME ) { 611 NbtAddress[] addrs; 612 613 try { 614 addrs = CLIENT.getNodeStatus( this ); 615 if( hostName.hexCode == 0x1D ) { 616 for( int i = 0; i < addrs.length; i++ ) { 617 if( addrs[i].hostName.hexCode == 0x20 ) { 618 return addrs[i].hostName.name; 619 } 620 } 621 return null; 622 } else if( isDataFromNodeStatus ) { 623 626 calledName = null; 627 return hostName.name; 628 } 629 } catch( UnknownHostException uhe ) { 630 calledName = null; 631 } 632 } else { 633 calledName = null; 634 } 635 636 return calledName; 637 } 638 639 665 666 void checkData() throws UnknownHostException { 667 if( hostName == UNKNOWN_NAME ) { 668 getAllByAddress( this ); 669 } 670 } 671 void checkNodeStatusData() throws UnknownHostException { 672 if( isDataFromNodeStatus == false ) { 673 getAllByAddress( this ); 674 } 675 } 676 677 683 684 public boolean isGroupAddress() throws UnknownHostException { 685 checkData(); 686 return groupName; 687 } 688 689 697 698 public int getNodeType() throws UnknownHostException { 699 checkData(); 700 return nodeType; 701 } 702 703 708 709 public boolean isBeingDeleted() throws UnknownHostException { 710 checkNodeStatusData(); 711 return isBeingDeleted; 712 } 713 714 719 720 public boolean isInConflict() throws UnknownHostException { 721 checkNodeStatusData(); 722 return isInConflict; 723 } 724 725 730 731 public boolean isActive() throws UnknownHostException { 732 checkNodeStatusData(); 733 return isActive; 734 } 735 736 741 742 public boolean isPermanent() throws UnknownHostException { 743 checkNodeStatusData(); 744 return isPermanent; 745 } 746 747 754 755 public byte[] getMacAddress() throws UnknownHostException { 756 checkNodeStatusData(); 757 return macAddress; 758 } 759 760 766 767 public String getHostName() { 768 try { 769 checkData(); 770 } catch( UnknownHostException uhe ) { 771 return getHostAddress(); 772 } 773 return hostName.name; 774 } 775 776 777 783 784 public byte[] getAddress() { 785 byte[] addr = new byte[4]; 786 787 addr[0] = (byte)(( address >>> 24 ) & 0xFF ); 788 addr[1] = (byte)(( address >>> 16 ) & 0xFF ); 789 addr[2] = (byte)(( address >>> 8 ) & 0xFF ); 790 addr[3] = (byte)( address & 0xFF ); 791 return addr; 792 } 793 794 799 800 public InetAddress getInetAddress() throws UnknownHostException { 801 return InetAddress.getByName( getHostAddress() ); 802 } 803 804 807 808 public String getHostAddress() { 809 return (( address >>> 24 ) & 0xFF ) + "." + 810 (( address >>> 16 ) & 0xFF ) + "." + 811 (( address >>> 8 ) & 0xFF ) + "." + 812 (( address >>> 0 ) & 0xFF ); 813 } 814 815 818 819 public int getNameType() { 820 return hostName.hexCode; 821 } 822 823 829 830 public int hashCode() { 831 return address; 832 } 833 834 839 840 public boolean equals( Object obj ) { 841 return ( obj != null ) && ( obj instanceof NbtAddress ) && 842 ( ((NbtAddress)obj).address == address ); 843 } 844 845 848 849 public String toString() { 850 return hostName.toString() + "/" + getHostAddress(); 851 } 852 } 853 | Popular Tags |