All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jcifs.netbios.NbtAddress Maven / Gradle / Ivy

There is a newer version: 2.1.10
Show newest version
/* jcifs smb client library in Java
 * Copyright (C) 2000  "Michael B. Allen" 
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package jcifs.netbios;


import java.net.InetAddress;
import java.net.UnknownHostException;

import jcifs.Address;
import jcifs.CIFSContext;
import jcifs.NetbiosAddress;
import jcifs.NetbiosName;


/**
 * This class represents a NetBIOS over TCP/IP address. Under normal
 * conditions, users of jCIFS need not be concerned with this class as
 * name resolution and session services are handled internally by the smb package.
 * 
 * 

* Applications can use the methods getLocalHost, * getByName, and * getAllByAddress to create a new NbtAddress instance. This * class is symmetric with {@link java.net.InetAddress}. * *

* About NetBIOS: The NetBIOS name * service is a dynamic distributed service that allows hosts to resolve * names by broadcasting a query, directing queries to a server such as * Samba or WINS. NetBIOS is currently the primary networking layer for * providing name service, datagram service, and session service to the * Microsoft Windows platform. A NetBIOS name can be 15 characters long * and hosts usually registers several names on the network. From a * Windows command prompt you can see * what names a host registers with the nbtstat command. *

*

* *
 * C:\>nbtstat -a 192.168.1.15
 * 
 *        NetBIOS Remote Machine Name Table
 * 
 *    Name               Type         Status
 * ---------------------------------------------
 * JMORRIS2        <00>  UNIQUE      Registered
 * BILLING-NY      <00>  GROUP       Registered
 * JMORRIS2        <03>  UNIQUE      Registered
 * JMORRIS2        <20>  UNIQUE      Registered
 * BILLING-NY      <1E>  GROUP       Registered
 * JMORRIS         <03>  UNIQUE      Registered
 * 
 * MAC Address = 00-B0-34-21-FA-3B
 * 
* *
*

* The hostname of this machine is JMORRIS2. It is * a member of the group(a.k.a workgroup and domain) BILLING-NY. To * obtain an {@link java.net.InetAddress} for a host one might do: * *

 * 
 * InetAddress addr = NbtAddress.getByName("jmorris2").getInetAddress();
 * 
*

* From a UNIX platform with Samba installed you can perform similar * diagnostics using the nmblookup utility. * * @author Michael B. Allen * @see java.net.InetAddress * @since jcifs-0.1 */ public final class NbtAddress implements NetbiosAddress { /** * This is a special name that means all hosts. If you wish to find all hosts * on a network querying a workgroup group name is the preferred method. */ public static final String ANY_HOSTS_NAME = "*\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"; /** * This is a special name for querying the master browser that serves the * list of hosts found in "Network Neighborhood". */ public static final String MASTER_BROWSER_NAME = "\u0001\u0002__MSBROWSE__\u0002"; /** * A special generic name specified when connecting to a host for which * a name is not known. Not all servers respond to this name. */ public static final String SMBSERVER_NAME = "*SMBSERVER "; /** * A B node only broadcasts name queries. This is the default if a * nameserver such as WINS or Samba is not specified. */ public static final int B_NODE = 0; /** * A Point-to-Point node, or P node, unicasts queries to a nameserver * only. Natrually the jcifs.netbios.nameserver property must * be set. */ public static final int P_NODE = 1; /** * Try Broadcast queries first, then try to resolve the name using the * nameserver. */ public static final int M_NODE = 2; /** * A Hybrid node tries to resolve a name using the nameserver first. If * that fails use the broadcast address. This is the default if a nameserver * is provided. This is the behavior of Microsoft Windows machines. */ public static final int H_NODE = 3; /** * Unknown MAC Address */ public static final byte[] UNKNOWN_MAC_ADDRESS = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; Name hostName; int address, nodeType; boolean groupName, isBeingDeleted, isInConflict, isActive, isPermanent, isDataFromNodeStatus; byte[] macAddress; String calledName; NbtAddress ( Name hostName, int address, boolean groupName, int nodeType ) { this.hostName = hostName; this.address = address; this.groupName = groupName; this.nodeType = nodeType; } NbtAddress ( Name hostName, int address, boolean groupName, int nodeType, boolean isBeingDeleted, boolean isInConflict, boolean isActive, boolean isPermanent, byte[] macAddress ) { /* * The NodeStatusResponse.readNodeNameArray method may also set this * information. These two places where node status data is populated should * be consistent. Be carefull! */ this.hostName = hostName; this.address = address; this.groupName = groupName; this.nodeType = nodeType; this.isBeingDeleted = isBeingDeleted; this.isInConflict = isInConflict; this.isActive = isActive; this.isPermanent = isPermanent; this.macAddress = macAddress; this.isDataFromNodeStatus = true; } /** * {@inheritDoc} * * @see jcifs.Address#unwrap(java.lang.Class) */ @SuppressWarnings ( "unchecked" ) @Override public T unwrap ( Class type ) { if ( type.isAssignableFrom(this.getClass()) ) { return (T) this; } return null; } /** * Guess next called name to try for session establishment. These * methods are used by the smb package. * * @return guessed name */ @Override public String firstCalledName () { this.calledName = this.hostName.name; if ( Character.isDigit(this.calledName.charAt(0)) ) { int i, len, dots; char[] data; i = dots = 0; /* quick IP address validation */ len = this.calledName.length(); data = this.calledName.toCharArray(); while ( i < len && Character.isDigit(data[ i++ ]) ) { if ( i == len && dots == 3 ) { // probably an IP address this.calledName = SMBSERVER_NAME; break; } if ( i < len && data[ i ] == '.' ) { dots++; i++; } } } else { switch ( this.hostName.hexCode ) { case 0x1B: case 0x1C: case 0x1D: this.calledName = SMBSERVER_NAME; } } return this.calledName; } /** * * @param tc * context to use * @return net name to try */ @Override public String nextCalledName ( CIFSContext tc ) { if ( this.calledName == this.hostName.name ) { this.calledName = SMBSERVER_NAME; } else if ( SMBSERVER_NAME.equals(this.calledName) ) { NetbiosAddress[] addrs; try { addrs = tc.getNameServiceClient().getNodeStatus(this); if ( this.getNameType() == 0x1D ) { for ( int i = 0; i < addrs.length; i++ ) { if ( addrs[ i ].getNameType() == 0x20 ) { return addrs[ i ].getHostName(); } } return null; } else if ( this.isDataFromNodeStatus ) { /* * 'this' has been updated and should now * have a real NetBIOS name */ this.calledName = null; return getHostName(); } } catch ( UnknownHostException uhe ) { this.calledName = null; } } else { this.calledName = null; } return this.calledName; } /* * There are three degrees of state that any NbtAddress can have. * * 1) IP Address - If a dot-quad IP string is used with getByName (or used * to create an NbtAddress internal to this netbios package), no query is * sent on the wire and the only state this object has is it's IP address * (but that's enough to connect to a host using *SMBSERVER for CallingName). * * 2) IP Address, NetBIOS name, nodeType, groupName - If however a * legal NetBIOS name string is used a name query request will retreive * the IP, node type, and whether or not this NbtAddress represents a * group name. This degree of state can be obtained with a Name Query * Request or Node Status Request. * * 3) All - The NbtAddress will be populated with all state such as mac * address, isPermanent, isBeingDeleted, ...etc. This information can only * be retrieved with the Node Status request. * * The degree of state that an NbtAddress has is dependant on how it was * created and what is required of it. The second degree of state is the * most common. This is the state information that would be retrieved from * WINS for example. Natrually it is not practical for every NbtAddress * to be populated will all state requiring a Node Status on every host * encountered. The below methods allow state to be populated when requested * in a lazy fashon. */ void checkData ( CIFSContext tc ) throws UnknownHostException { if ( this.hostName.isUnknown() ) { tc.getNameServiceClient().getNbtAllByAddress(this); } } void checkNodeStatusData ( CIFSContext tc ) throws UnknownHostException { if ( this.isDataFromNodeStatus == false ) { tc.getNameServiceClient().getNbtAllByAddress(this); } } @Override public boolean isGroupAddress ( CIFSContext tc ) throws UnknownHostException { checkData(tc); return this.groupName; } @Override public int getNodeType ( CIFSContext tc ) throws UnknownHostException { checkData(tc); return this.nodeType; } @Override public boolean isBeingDeleted ( CIFSContext tc ) throws UnknownHostException { checkNodeStatusData(tc); return this.isBeingDeleted; } @Override public boolean isInConflict ( CIFSContext tc ) throws UnknownHostException { checkNodeStatusData(tc); return this.isInConflict; } @Override public boolean isActive ( CIFSContext tc ) throws UnknownHostException { checkNodeStatusData(tc); return this.isActive; } @Override public boolean isPermanent ( CIFSContext tc ) throws UnknownHostException { checkNodeStatusData(tc); return this.isPermanent; } @Override public byte[] getMacAddress ( CIFSContext tc ) throws UnknownHostException { checkNodeStatusData(tc); return this.macAddress; } /** * The hostname of this address. If the hostname is null the local machines * IP address is returned. * * @return the text representation of the hostname associated with this address */ @Override public String getHostName () { /* * 2010 - We no longer try a Node Status to get the * hostname because apparently some servers do not respond * anymore. I think everyone post Windows 98 will accept * an IP address as the tconHostName which is the principal * use of this method. */ if ( this.hostName.isUnknown() ) { return getHostAddress(); } return this.hostName.name; } @Override public NetbiosName getName () { return this.hostName; } /** * Returns the raw IP address of this NbtAddress. The result is in network * byte order: the highest order byte of the address is in getAddress()[0]. * * @return a four byte array */ public byte[] getAddress () { byte[] addr = new byte[4]; addr[ 0 ] = (byte) ( ( this.address >>> 24 ) & 0xFF ); addr[ 1 ] = (byte) ( ( this.address >>> 16 ) & 0xFF ); addr[ 2 ] = (byte) ( ( this.address >>> 8 ) & 0xFF ); addr[ 3 ] = (byte) ( this.address & 0xFF ); return addr; } /** * To convert this address to an InetAddress. * * @return the {@link java.net.InetAddress} representation of this address. * @throws UnknownHostException */ public InetAddress getInetAddress () throws UnknownHostException { return InetAddress.getByName(getHostAddress()); } @Override public InetAddress toInetAddress () throws UnknownHostException { return getInetAddress(); } /** * Returns this IP adress as a {@link java.lang.String} in the form "%d.%d.%d.%d". * * @return string representation of the IP address */ @Override public String getHostAddress () { return ( ( this.address >>> 24 ) & 0xFF ) + "." + ( ( this.address >>> 16 ) & 0xFF ) + "." + ( ( this.address >>> 8 ) & 0xFF ) + "." + ( ( this.address >>> 0 ) & 0xFF ); } @Override public int getNameType () { return this.hostName.hexCode; } /** * Returns a hashcode for this IP address. The hashcode comes from the IP address * and is not generated from the string representation. So because NetBIOS nodes * can have many names, all names associated with an IP will have the same * hashcode. */ @Override public int hashCode () { return this.address; } /** * Determines if this address is equal two another. Only the IP Addresses * are compared. Similar to the {@link #hashCode} method, the comparison * is based on the integer IP address and not the string representation. */ @Override public boolean equals ( Object obj ) { return ( obj != null ) && ( obj instanceof NbtAddress ) && ( ( (NbtAddress) obj ).address == this.address ); } /** * Returns the {@link java.lang.String} representaion of this address. */ @Override public String toString () { return this.hostName.toString() + "/" + getHostAddress(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy