2005-12-08 07:13:07 +00:00

714 lines
19 KiB
Java

/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.filesys.netbios.win32;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.Hashtable;
import org.alfresco.filesys.netbios.NetBIOSName;
import org.alfresco.filesys.util.DataBuffer;
import org.alfresco.filesys.util.IPAddress;
/**
* Win32 NetBIOS Native Call Wrapper Class
*/
public class Win32NetBIOS
{
// Constants
//
// FIND_NAME_BUFFER structure length
protected final static int FindNameBufferLen = 33;
// Exception if the native code DLL load failed
private static Throwable m_loadDLLException;
/**
* Check if the native code was loaded successfully
*
* @return boolean
*/
public static final boolean isInitialized()
{
return m_loadDLLException == null ? true : false;
}
/**
* Return the native code load exception
*
* @return Throwable
*/
public static final Throwable getInitializationException()
{
return m_loadDLLException;
}
/**
* Check if NetBIOS is enabled on any network adapters
*
* @return boolean
*/
public static final boolean isAvailable() {
// Check if the DLL was loaded successfully
if ( isInitialized() == false)
return false;
// Check if there are any valid LANAs, if not then NetBIOS is not enabled or network
// adapters that have NetBIOS enabled are not currently enabled
int[] lanas = LanaEnum();
if ( lanas != null && lanas.length > 0)
return true;
return false;
}
/**
* Add a NetBIOS name to the local name table
*
* @param lana int
* @param name byte[]
* @return int
*/
public static native int AddName(int lana, byte[] name);
/**
* Add a group NetBIOS name to the local name table
*
* @param lana int
* @param name byte[]
* @return int
*/
public static native int AddGroupName(int lana, byte[] name);
/**
* Find a NetBIOS name, return the name buffer
*
* @param lana int
* @param name byte[]
* @param nameBuf byte[]
* @param bufLen int
* @return int
*/
public static native int FindNameRaw(int lana, byte[] name, byte[] nameBuf, int bufLen);
/**
* Find a NetBIOS name
*
* @param lana int
* @param name NetBIOSName
* @return int
*/
public static int FindName(int lana, NetBIOSName nbName)
{
// Allocate a buffer to receive the name details
byte[] nameBuf = new byte[nbName.isGroupName() ? 65535 : 4096];
// Get the raw NetBIOS name data
int sts = FindNameRaw(lana, nbName.getNetBIOSName(), nameBuf, nameBuf.length);
if (sts != NetBIOS.NRC_GoodRet)
return -sts;
// Unpack the FIND_NAME_HEADER structure
DataBuffer buf = new DataBuffer(nameBuf, 0, nameBuf.length);
int nodeCount = buf.getShort();
buf.skipBytes(1);
boolean isGroupName = buf.getByte() == 0 ? false : true;
// Unpack the FIND_NAME_BUFFER structures
int curPos = buf.getPosition();
for (int i = 0; i < nodeCount; i++)
{
// FIND_NAME_BUFFER:
// UCHAR length
// UCHAR access_control
// UCHAR frame_control
// UCHAR destination_addr[6]
// UCHAR source_addr[6]
// UCHAR routing_info[18]
// Skip to the source_addr field
buf.skipBytes(9);
// Source address field format should be 0.0.n.n.n.n for TCP/IP address
if (buf.getByte() == 0 && buf.getByte() == 0)
{
// Looks like a TCP/IP format address, unpack it
byte[] ipAddr = new byte[4];
ipAddr[0] = (byte) buf.getByte();
ipAddr[1] = (byte) buf.getByte();
ipAddr[2] = (byte) buf.getByte();
ipAddr[3] = (byte) buf.getByte();
// Add the address to the list of TCP/IP addresses for the NetBIOS name
nbName.addIPAddress(ipAddr);
// Skip to the start of the next FIND_NAME_BUFFER structure
curPos += FindNameBufferLen;
buf.setPosition(curPos);
}
}
// Return the node count
return nodeCount;
}
/**
* Delete a NetBIOS name from the local name table
*
* @param lana int
* @param name byte[]
* @return int
*/
public static native int DeleteName(int lana, byte[] name);
/**
* Enumerate the available LANAs
*
* @return int[]
*/
public static int[] LanaEnumerate()
{
// Make sure that there is an active network adapter as making calls to the LanaEnum native call
// causes problems when there are no active network adapters.
boolean adapterAvail = false;
try
{
// Enumerate the available network adapters and check for an active adapter, not including
// the loopback adapter
Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
while ( nis.hasMoreElements() && adapterAvail == false)
{
NetworkInterface ni = nis.nextElement();
if ( ni.getName().equals("lo") == false)
{
// Make sure the adapter has a valid IP address
Enumeration<InetAddress> addrs = ni.getInetAddresses();
if ( addrs.hasMoreElements())
adapterAvail = true;
}
}
}
catch ( SocketException ex)
{
}
// Check if there are network adapter(s) available
if ( adapterAvail == false)
return null;
// Call the native code to return the available LANA list
return LanaEnum();
}
/**
* Enumerate the available LANAs
*
* @return int[]
*/
private static native int[] LanaEnum();
/**
* Reset the NetBIOS environment
*
* @param lana int
* @return int
*/
public static native int Reset(int lana);
/**
* Listen for an incoming session request
*
* @param lana int
* @param toName byte[]
* @param fromName byte[]
* @param callerName byte[]
* @return int
*/
public static native int Listen(int lana, byte[] toName, byte[] fromName, byte[] callerName);
/**
* Receive a data packet on a session
*
* @param lana int
* @param lsn int
* @param buf byte[]
* @param off int
* @param maxLen int
* @return int
*/
public static native int Receive(int lana, int lsn, byte[] buf, int off, int maxLen);
/**
* Send a data packet on a session
*
* @param lana int
* @param lsn int
* @param buf byte[]
* @param off int
* @param len int
* @return int
*/
public static native int Send(int lana, int lsn, byte[] buf, int off, int len);
/**
* Send a datagram to a specified name
*
* @param lana int
* @param srcNum int
* @param destName byte[]
* @param buf byte[]
* @param off int
* @param len int
* @return int
*/
public static native int SendDatagram(int lana, int srcNum, byte[] destName, byte[] buf, int off, int len);
/**
* Send a broadcast datagram
*
* @param lana
* @param buf byte[]
* @param off int
* @param len int
* @return int
*/
public static native int SendBroadcastDatagram(int lana, byte[] buf, int off, int len);
/**
* Receive a datagram on a specified name
*
* @param lana int
* @param nameNum int
* @param buf byte[]
* @param off int
* @param maxLen int
* @return int
*/
public static native int ReceiveDatagram(int lana, int nameNum, byte[] buf, int off, int maxLen);
/**
* Receive a broadcast datagram
*
* @param lana int
* @param nameNum int
* @param buf byte[]
* @param off int
* @param maxLen int
* @return int
*/
public static native int ReceiveBroadcastDatagram(int lana, int nameNum, byte[] buf, int off, int maxLen);
/**
* Hangup a session
*
* @param lsn int
* @return int
*/
public static native int Hangup(int lana, int lsn);
/**
* Return the local computers NetBIOS name
*
* @return String
*/
public static native String GetLocalNetBIOSName();
/**
* Return the local domain name
*
* @return String
*/
public static native String GetLocalDomainName();
/**
* Return a comma delimeted list of WINS server TCP/IP addresses, or null if no WINS servers are
* configured.
*
* @return String
*/
public static native String getWINSServerList();
/**
* Find the TCP/IP address for a LANA
*
* @param lana int
* @return String
*/
public static final String getIPAddressForLANA(int lana)
{
// Get the local NetBIOS name
String localName = GetLocalNetBIOSName();
if (localName == null)
return null;
// Create a NetBIOS name for the local name
NetBIOSName nbName = new NetBIOSName(localName, NetBIOSName.WorkStation, false);
// Get the local NetBIOS name details
int sts = FindName(lana, nbName);
if (sts == -NetBIOS.NRC_EnvNotDef)
{
// Reset the LANA then try the name lookup again
Reset(lana);
sts = FindName(lana, nbName);
}
// Check if the name lookup was successful
String ipAddr = null;
if (sts >= 0)
{
// Get the first IP address from the list
ipAddr = nbName.getIPAddressString(0);
}
// Return the TCP/IP address for the LANA
return ipAddr;
}
/**
* Find the adapter name for a LANA
*
* @param lana int
* @return String
*/
public static final String getAdapterNameForLANA(int lana)
{
// Get the TCP/IP address for a LANA
String ipAddr = getIPAddressForLANA(lana);
if (ipAddr == null)
return null;
// Get the list of available network adapters
Hashtable<String, NetworkInterface> adapters = getNetworkAdapterList();
String adapterName = null;
if (adapters != null)
{
// Find the network adapter for the TCP/IP address
NetworkInterface ni = adapters.get(ipAddr);
if (ni != null)
adapterName = ni.getDisplayName();
}
// Return the adapter name for the LANA
return adapterName;
}
/**
* Find the LANA for a TCP/IP address
*
* @param addr String
* @return int
*/
public static final int getLANAForIPAddress(String addr)
{
// Check if the address is a numeric TCP/IP address
if (IPAddress.isNumericAddress(addr) == false)
return -1;
// Get a list of the available NetBIOS LANAs
int[] lanas = LanaEnum();
if (lanas == null || lanas.length == 0)
return -1;
// Search for the LANA with the matching TCP/IP address
for (int i = 0; i < lanas.length; i++)
{
// Get the current LANAs TCP/IP address
String curAddr = getIPAddressForLANA(lanas[i]);
if (curAddr != null && curAddr.equals(addr))
return lanas[i];
}
// Failed to find the LANA for the specified TCP/IP address
return -1;
}
/**
* Find the LANA for a network adapter
*
* @param name String
* @return int
*/
public static final int getLANAForAdapterName(String name)
{
// Get the list of available network adapters
Hashtable<String, NetworkInterface> niList = getNetworkAdapterList();
// Search for the address of the specified network adapter
Enumeration<String> niEnum = niList.keys();
while (niEnum.hasMoreElements())
{
// Get the current TCP/IP address
String ipAddr = niEnum.nextElement();
NetworkInterface ni = niList.get(ipAddr);
if (ni.getDisplayName().equalsIgnoreCase(name))
{
// Return the LANA for the network adapters TCP/IP address
return getLANAForIPAddress(ipAddr);
}
}
// Failed to find matching network adapter
return -1;
}
/**
* Return a hashtable of NetworkInterfaces indexed by TCP/IP address
*
* @return Hashtable<String,NetworkInterface>
*/
private static final Hashtable<String, NetworkInterface> getNetworkAdapterList()
{
// Get a list of the local network adapters
Hashtable<String, NetworkInterface> niList = new Hashtable<String, NetworkInterface>();
try
{
// Enumerate the available network adapters
Enumeration<NetworkInterface> niEnum = NetworkInterface.getNetworkInterfaces();
while (niEnum.hasMoreElements())
{
// Get the current network interface details
NetworkInterface ni = niEnum.nextElement();
Enumeration<InetAddress> addrEnum = ni.getInetAddresses();
while (addrEnum.hasMoreElements())
{
// Get the address and add the adapter to the list indexed via the numeric IP
// address string
InetAddress addr = addrEnum.nextElement();
niList.put(addr.getHostAddress(), ni);
}
}
}
catch (Exception ex)
{
}
// Return the network adapter list
return niList;
}
//---------- Winsock based NetBIOS interface ----------//
/**
* Initialize the NetBIOS socket interface
*
* @exception WinsockNetBIOSException If a Winsock error occurs
*/
protected static native void InitializeSockets()
throws WinsockNetBIOSException;
/**
* Shutdown the NetBIOS socket interface
*/
protected static native void ShutdownSockets();
/**
* Create a NetBIOS socket
*
* @param lana int
* @return int
* @exception WinsockNetBIOSException If a Winsock error occurs
*/
protected static native int CreateSocket(int lana)
throws WinsockNetBIOSException;
/**
* Create a NetBIOS datagram socket
*
* @param lana int
* @return int
* @exception WinsockNetBIOSException If a Winsock error occurs
*/
protected static native int CreateDatagramSocket(int lana)
throws WinsockNetBIOSException;
/**
* Bind a NetBIOS socket to a name to listen for incoming sessions
*
* @param sockPtr int
* @param name byte[]
* @exception WinsockNetBIOSException If a Winsock error occurs
*/
protected static native int BindSocket(int sockPtr, byte[] name)
throws WinsockNetBIOSException;
/**
* Listen for an incoming connection
*
* @param sockPtr int
* @param callerName byte[]
* @return int
* @exception WinsockNetBIOSException If a Winsock error occurs
*/
protected static native int ListenSocket(int sockPtr, byte[] callerName)
throws WinsockNetBIOSException;
/**
* Close a NetBIOS socket
*
* @param sockPtr int
*/
protected static native void CloseSocket(int sockPtr);
/**
* Send data on a session socket
*
* @param sockPtr int
* @param buf byte[]
* @param off int
* @param len int
* @return int
* @exception WinsockNetBIOSException If a Winsock error occurs
*/
protected static native int SendSocket(int sockPtr, byte[] buf, int off, int len)
throws WinsockNetBIOSException;
/**
* Receive data on a session socket
*
* @param sockPtr int
* @param toName byte[]
* @param buf byte[]
* @param off int
* @param maxLen int
* @return int
* @exception WinsockNetBIOSException If a Winsock error occurs
*/
protected static native int ReceiveSocket(int sockPtr, byte[] buf, int off, int maxLen)
throws WinsockNetBIOSException;
/**
* Send data on a datagram socket
*
* @param sockPtr int
* @param toName byte[]
* @param buf byte[]
* @param off int
* @param len int
* @return int
* @exception WinsockNetBIOSException If a Winsock error occurs
*/
protected static native int SendSocketDatagram(int sockPtr, byte[] toName, byte[] buf, int off, int len)
throws WinsockNetBIOSException;
/**
* Wait for a network address change event, block until a change occurs or the Winsock NetBIOS
* interface is shut down
*/
public static native void waitForNetworkAddressChange();
/**
* Static initializer used to load the native code library
*/
static
{
// Load the Win32 NetBIOS interface library
try
{
System.loadLibrary("Win32NetBIOS");
}
catch (Throwable ex)
{
// Save the native code load exception
m_loadDLLException = ex;
}
}
}