1 18 19 package 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 import jcifs.Config; 28 import jcifs.util.Hexdump; 29 30 79 80 public final class NbtAddress { 81 82 86 87 static final String ANY_HOSTS_NAME = "*\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"; 88 89 93 94 public static final String MASTER_BROWSER_NAME = "\u0001\u0002__MSBROWSE__\u0002"; 95 96 100 101 public static final String SMBSERVER_NAME = "*SMBSERVER "; 102 103 107 108 public static final int B_NODE = 0; 109 110 115 116 public static final int P_NODE = 1; 117 118 122 123 public static final int M_NODE = 2; 124 125 130 131 public static final int H_NODE = 3; 132 133 static final InetAddress [] NBNS = Config.getInetAddressArray( "jcifs.netbios.wins", ",", new InetAddress [0] ); 134 135 139 140 private static final NameServiceClient CLIENT = new NameServiceClient(); 141 142 private static final int DEFAULT_CACHE_POLICY = 30; 143 private static final int CACHE_POLICY = Config.getInt( "jcifs.netbios.cachePolicy", DEFAULT_CACHE_POLICY ); 144 private static final int FOREVER = -1; 145 private static int nbnsIndex = 0; 146 147 private static final HashMap ADDRESS_CACHE = new HashMap (); 148 private static final HashMap LOOKUP_TABLE = new HashMap (); 149 150 static final Name UNKNOWN_NAME = new Name( "0.0.0.0", 0x00, null ); 151 static final NbtAddress UNKNOWN_ADDRESS = new NbtAddress( UNKNOWN_NAME, 0, false, B_NODE ); 152 static final byte[] UNKNOWN_MAC_ADDRESS = new byte[] { 153 (byte)0x00, (byte)0x00, (byte)0x00, 154 (byte)0x00, (byte)0x00, (byte)0x00 155 }; 156 157 static final class CacheEntry { 158 Name hostName; 159 NbtAddress address; 160 long expiration; 161 162 CacheEntry( Name hostName, NbtAddress address, long expiration ) { 163 this.hostName = hostName; 164 this.address = address; 165 this.expiration = expiration; 166 } 167 } 168 169 static NbtAddress localhost; 170 171 static { 172 InetAddress localInetAddress; 173 String localHostname; 174 Name localName; 175 176 178 179 ADDRESS_CACHE.put( UNKNOWN_NAME, new CacheEntry( UNKNOWN_NAME, UNKNOWN_ADDRESS, FOREVER )); 180 181 184 localInetAddress = CLIENT.laddr; 185 if( localInetAddress == null ) { 186 try { 187 localInetAddress = InetAddress.getLocalHost(); 188 } catch( UnknownHostException uhe ) { 189 } 190 } 191 192 197 localHostname = Config.getProperty( "jcifs.netbios.hostname", null ); 198 if( localHostname == null || localHostname.length() == 0 ) { 199 byte[] addr = localInetAddress.getAddress(); 200 localHostname = "JCIFS" + 201 ( addr[2] & 0xFF ) + "_" + 202 ( addr[3] & 0xFF ) + "_" + 203 Hexdump.toHexString( (int)( Math.random() * (double)0xFF ), 2 ); 204 } 205 206 210 localName = new Name( localHostname, 0x00, 211 Config.getProperty( "jcifs.netbios.scope", null )); 212 localhost = new NbtAddress( localName, 213 localInetAddress.hashCode(), 214 false, 215 B_NODE, 216 false, false, true, false, 217 UNKNOWN_MAC_ADDRESS ); 218 cacheAddress( localName, localhost, FOREVER ); 219 } 220 221 static void cacheAddress( Name hostName, NbtAddress addr ) { 222 if( CACHE_POLICY == 0 ) { 223 return; 224 } 225 long expiration = -1; 226 if( CACHE_POLICY != FOREVER ) { 227 expiration = System.currentTimeMillis() + CACHE_POLICY * 1000; 228 } 229 cacheAddress( hostName, addr, expiration ); 230 } 231 static void cacheAddress( Name hostName, NbtAddress addr, long expiration ) { 232 if( CACHE_POLICY == 0 ) { 233 return; 234 } 235 synchronized( ADDRESS_CACHE ) { 236 CacheEntry entry = (CacheEntry)ADDRESS_CACHE.get( hostName ); 237 if( entry == null ) { 238 entry = new CacheEntry( hostName, addr, expiration ); 239 ADDRESS_CACHE.put( hostName, entry ); 240 } else { 241 entry.address = addr; 242 entry.expiration = expiration; 243 } 244 } 245 } 246 static void cacheAddressArray( NbtAddress[] addrs ) { 247 if( CACHE_POLICY == 0 ) { 248 return; 249 } 250 long expiration = -1; 251 if( CACHE_POLICY != FOREVER ) { 252 expiration = System.currentTimeMillis() + CACHE_POLICY * 1000; 253 } 254 synchronized( ADDRESS_CACHE ) { 255 for( int i = 0; i < addrs.length; i++ ) { 256 CacheEntry entry = (CacheEntry)ADDRESS_CACHE.get( addrs[i].hostName ); 257 if( entry == null ) { 258 entry = new CacheEntry( addrs[i].hostName, addrs[i], expiration ); 259 ADDRESS_CACHE.put( addrs[i].hostName, entry ); 260 } else { 261 entry.address = addrs[i]; 262 entry.expiration = expiration; 263 } 264 } 265 } 266 } 267 static NbtAddress getCachedAddress( Name hostName ) { 268 if( CACHE_POLICY == 0 ) { 269 return null; 270 } 271 synchronized( ADDRESS_CACHE ) { 272 CacheEntry entry = (CacheEntry)ADDRESS_CACHE.get( hostName ); 273 if( entry != null && entry.expiration < System.currentTimeMillis() && 274 entry.expiration >= 0 ) { 275 entry = null; 276 } 277 return entry != null ? entry.address : null; 278 } 279 } 280 281 static NbtAddress doNameQuery( Name name, InetAddress svr ) 282 throws UnknownHostException { 283 NbtAddress addr; 284 285 if( name.hexCode == 0x1d && svr == null ) { 286 svr = CLIENT.baddr; } 288 name.srcHashCode = svr != null ? svr.hashCode() : 0; 289 addr = getCachedAddress( name ); 290 291 if( addr == null ) { 292 296 if(( addr = (NbtAddress)checkLookupTable( name )) == null ) { 297 try { 298 addr = CLIENT.getByName( name, svr ); 299 } catch( UnknownHostException uhe ) { 300 addr = UNKNOWN_ADDRESS; 301 } finally { 302 cacheAddress( name, addr ); 303 updateLookupTable( name ); 304 } 305 } 306 } 307 if( addr == UNKNOWN_ADDRESS ) { 308 throw new UnknownHostException ( name.toString() ); 309 } 310 return addr; 311 } 312 313 private static Object checkLookupTable( Name name ) { 314 Object obj; 315 316 synchronized( LOOKUP_TABLE ) { 317 if( LOOKUP_TABLE.containsKey( name ) == false ) { 318 LOOKUP_TABLE.put( name, name ); 319 return null; 320 } 321 while( LOOKUP_TABLE.containsKey( name )) { 322 try { 323 LOOKUP_TABLE.wait(); 324 } catch( InterruptedException e ) { 325 } 326 } 327 } 328 obj = getCachedAddress( name ); 329 if( obj == null ) { 330 synchronized( LOOKUP_TABLE ) { 331 LOOKUP_TABLE.put( name, name ); 332 } 333 } 334 335 return obj; 336 } 337 private static void updateLookupTable( Name name ) { 338 synchronized( LOOKUP_TABLE ) { 339 LOOKUP_TABLE.remove( name ); 340 LOOKUP_TABLE.notifyAll(); 341 } 342 } 343 344 350 351 public static NbtAddress getLocalHost() throws UnknownHostException { 352 return localhost; 353 } 354 public static Name getLocalName() { 355 return localhost.hostName; 356 } 357 358 367 368 public static NbtAddress getByName( String host ) 369 throws UnknownHostException { 370 return getByName( host, 0x00, null ); 371 } 372 373 388 389 public static NbtAddress getByName( String host, 390 int type, 391 String scope ) 392 throws UnknownHostException { 393 394 return getByName( host, type, scope, null ); 395 } 396 397 402 403 public static NbtAddress getByName( String host, 404 int type, 405 String scope, 406 InetAddress svr ) 407 throws UnknownHostException { 408 409 if( host == null || host.length() == 0 ) { 410 return getLocalHost(); 411 } 412 if( !Character.isDigit( host.charAt(0) )) { 413 return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr ); 414 } else { 415 int IP = 0x00; 416 int hitDots = 0; 417 char[] data = host.toCharArray(); 418 419 for( int i = 0; i < data.length; i++ ) { 420 char c = data[i]; 421 if( c < 48 || c > 57 ) { 422 return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr ); 423 } 424 int b = 0x00; 425 while( c != '.' ) { 426 if( c < 48 || c > 57 ) { 427 return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr ); 428 } 429 b = b * 10 + c - '0'; 430 431 if( ++i >= data.length ) 432 break; 433 434 c = data[i]; 435 } 436 if( b > 0xFF ) { 437 return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr ); 438 } 439 IP = ( IP << 8 ) + b; 440 hitDots++; 441 } 442 if( hitDots != 4 || host.endsWith( "." )) { 443 return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr ); 444 } 445 return new NbtAddress( UNKNOWN_NAME, IP, false, B_NODE ); 446 } 447 } 448 449 public static NbtAddress[] getAllByName( String host, 450 int type, 451 String scope, 452 InetAddress svr ) 453 throws UnknownHostException { 454 return CLIENT.getAllByName( new Name( host, type, scope ), svr ); 455 } 456 457 466 467 468 public static NbtAddress[] getAllByAddress( String host ) 469 throws UnknownHostException { 470 return getAllByAddress( getByName( host, 0x00, null )); 471 } 472 473 474 487 488 489 public static NbtAddress[] getAllByAddress( String host, 490 int type, 491 String scope ) 492 throws UnknownHostException { 493 return getAllByAddress( getByName( host, type, scope )); 494 } 495 496 497 506 507 public static NbtAddress[] getAllByAddress( NbtAddress addr ) 508 throws UnknownHostException { 509 try { 510 NbtAddress[] addrs = CLIENT.getNodeStatus( addr ); 511 cacheAddressArray( addrs ); 512 return addrs; 513 } catch( UnknownHostException uhe ) { 514 throw new UnknownHostException ( "no name with type 0x" + 515 Hexdump.toHexString( addr.hostName.hexCode, 2 ) + 516 ((( addr.hostName.scope == null ) || 517 ( addr.hostName.scope.length() == 0 )) ? 518 " with no scope" : " with scope " + addr.hostName.scope ) + 519 " for host " + addr.getHostAddress() ); 520 } 521 } 522 523 public static InetAddress getWINSAddress() { 524 return NBNS.length == 0 ? null : NBNS[nbnsIndex]; 525 } 526 public static boolean isWINS( InetAddress svr ) { 527 for( int i = 0; svr != null && i < NBNS.length; i++ ) { 528 if( svr.hashCode() == NBNS[i].hashCode() ) { 529 return true; 530 } 531 } 532 return false; 533 } 534 static InetAddress switchWINS() { 535 nbnsIndex = (nbnsIndex + 1) < NBNS.length ? nbnsIndex + 1 : 0; 536 return NBNS.length == 0 ? null : NBNS[nbnsIndex]; 537 } 538 539 Name hostName; 540 int address, nodeType; 541 boolean groupName, 542 isBeingDeleted, 543 isInConflict, 544 isActive, 545 isPermanent, 546 isDataFromNodeStatus; 547 byte[] macAddress; 548 String calledName; 549 550 NbtAddress( Name hostName, int address, boolean groupName, int nodeType ) { 551 this.hostName = hostName; 552 this.address = address; 553 this.groupName = groupName; 554 this.nodeType = nodeType; 555 } 556 557 NbtAddress( Name hostName, 558 int address, 559 boolean groupName, 560 int nodeType, 561 boolean isBeingDeleted, 562 boolean isInConflict, 563 boolean isActive, 564 boolean isPermanent, 565 byte[] macAddress ) { 566 567 571 this.hostName = hostName; 572 this.address = address; 573 this.groupName = groupName; 574 this.nodeType = nodeType; 575 this.isBeingDeleted = isBeingDeleted; 576 this.isInConflict = isInConflict; 577 this.isActive = isActive; 578 this.isPermanent = isPermanent; 579 this.macAddress = macAddress; 580 isDataFromNodeStatus = true; 581 } 582 583 586 587 public String firstCalledName() { 588 589 calledName = hostName.name; 590 591 if( Character.isDigit( calledName.charAt( 0 ))) { 592 int i, len, dots; 593 char[] data; 594 595 i = dots = 0; 596 len = calledName.length(); 597 data = calledName.toCharArray(); 598 while( i < len && Character.isDigit( data[i++] )) { 599 if( i == len && dots == 3 ) { 600 calledName = SMBSERVER_NAME; 602 break; 603 } 604 if( i < len && data[i] == '.' ) { 605 dots++; 606 i++; 607 } 608 } 609 } else { 610 switch (hostName.hexCode) { 611 case 0x1B: 612 case 0x1C: 613 case 0x1D: 614 calledName = SMBSERVER_NAME; 615 } 616 } 617 618 return calledName; 619 } 620 public String nextCalledName() { 621 622 if( calledName == hostName.name ) { 623 calledName = SMBSERVER_NAME; 624 } else if( calledName == SMBSERVER_NAME ) { 625 NbtAddress[] addrs; 626 627 try { 628 addrs = CLIENT.getNodeStatus( this ); 629 if( hostName.hexCode == 0x1D ) { 630 for( int i = 0; i < addrs.length; i++ ) { 631 if( addrs[i].hostName.hexCode == 0x20 ) { 632 return addrs[i].hostName.name; 633 } 634 } 635 return null; 636 } else if( isDataFromNodeStatus ) { 637 640 calledName = null; 641 return hostName.name; 642 } 643 } catch( UnknownHostException uhe ) { 644 calledName = null; 645 } 646 } else { 647 calledName = null; 648 } 649 650 return calledName; 651 } 652 653 679 680 void checkData() throws UnknownHostException { 681 if( hostName == UNKNOWN_NAME ) { 682 getAllByAddress( this ); 683 } 684 } 685 void checkNodeStatusData() throws UnknownHostException { 686 if( isDataFromNodeStatus == false ) { 687 getAllByAddress( this ); 688 } 689 } 690 691 697 698 public boolean isGroupAddress() throws UnknownHostException { 699 checkData(); 700 return groupName; 701 } 702 703 711 712 public int getNodeType() throws UnknownHostException { 713 checkData(); 714 return nodeType; 715 } 716 717 722 723 public boolean isBeingDeleted() throws UnknownHostException { 724 checkNodeStatusData(); 725 return isBeingDeleted; 726 } 727 728 733 734 public boolean isInConflict() throws UnknownHostException { 735 checkNodeStatusData(); 736 return isInConflict; 737 } 738 739 744 745 public boolean isActive() throws UnknownHostException { 746 checkNodeStatusData(); 747 return isActive; 748 } 749 750 755 756 public boolean isPermanent() throws UnknownHostException { 757 checkNodeStatusData(); 758 return isPermanent; 759 } 760 761 768 769 public byte[] getMacAddress() throws UnknownHostException { 770 checkNodeStatusData(); 771 return macAddress; 772 } 773 774 780 781 public String getHostName() { 782 try { 783 checkData(); 784 } catch( UnknownHostException uhe ) { 785 return getHostAddress(); 786 } 787 return hostName.name; 788 } 789 790 791 797 798 public byte[] getAddress() { 799 byte[] addr = new byte[4]; 800 801 addr[0] = (byte)(( address >>> 24 ) & 0xFF ); 802 addr[1] = (byte)(( address >>> 16 ) & 0xFF ); 803 addr[2] = (byte)(( address >>> 8 ) & 0xFF ); 804 addr[3] = (byte)( address & 0xFF ); 805 return addr; 806 } 807 808 813 814 public InetAddress getInetAddress() throws UnknownHostException { 815 return InetAddress.getByName( getHostAddress() ); 816 } 817 818 821 822 public String getHostAddress() { 823 return (( address >>> 24 ) & 0xFF ) + "." + 824 (( address >>> 16 ) & 0xFF ) + "." + 825 (( address >>> 8 ) & 0xFF ) + "." + 826 (( address >>> 0 ) & 0xFF ); 827 } 828 829 832 833 public int getNameType() { 834 return hostName.hexCode; 835 } 836 837 843 844 public int hashCode() { 845 return address; 846 } 847 848 853 854 public boolean equals( Object obj ) { 855 return ( obj != null ) && ( obj instanceof NbtAddress ) && 856 ( ((NbtAddress)obj).address == address ); 857 } 858 859 862 863 public String toString() { 864 return hostName.toString() + "/" + getHostAddress(); 865 } 866 } 867 | Popular Tags |