mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-02 17:35:18 +00:00
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
1247 lines
31 KiB
Java
1247 lines
31 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;
|
|
|
|
import org.alfresco.filesys.util.DataPacker;
|
|
import org.alfresco.filesys.util.HexDump;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
/**
|
|
* NetBIOS Packet Class
|
|
*/
|
|
public class NetBIOSPacket
|
|
{
|
|
private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol.netbios");
|
|
|
|
// Minimum valid receive length
|
|
|
|
public static final int MIN_RXLEN = 4;
|
|
|
|
// NetBIOS opcodes
|
|
|
|
public static final int NAME_QUERY = 0x00;
|
|
public static final int NAME_REGISTER = 0x05;
|
|
public static final int NAME_RELEASE = 0x06;
|
|
public static final int WACK = 0x07;
|
|
public static final int REFRESH = 0x08;
|
|
public static final int NAME_REGISTER_MULTI = 0x0F;
|
|
|
|
public static final int RESP_QUERY = 0x10;
|
|
public static final int RESP_REGISTER = 0x15;
|
|
public static final int RESP_RELEASE = 0x16;
|
|
|
|
// NetBIOS opcode masks
|
|
|
|
public static final int MASK_OPCODE = 0xF800;
|
|
public static final int MASK_NMFLAGS = 0x07F0;
|
|
public static final int MASK_RCODE = 0x000F;
|
|
|
|
public static final int MASK_NOOPCODE = 0x07FF;
|
|
public static final int MASK_NOFLAGS = 0xF80F;
|
|
public static final int MASK_NORCODE = 0xFFF0;
|
|
|
|
public static final int MASK_RESPONSE = 0x0010;
|
|
|
|
// Flags bit values
|
|
|
|
public static final int FLG_BROADCAST = 0x0001;
|
|
public static final int FLG_RECURSION = 0x0008;
|
|
public static final int FLG_RECURSDES = 0x0010;
|
|
public static final int FLG_TRUNCATION = 0x0020;
|
|
public static final int FLG_AUTHANSWER = 0x0040;
|
|
|
|
// NetBIOS name lookup types
|
|
|
|
public static final int NAME_TYPE_NB = 0x0020;
|
|
public static final int NAME_TYPE_NBSTAT = 0x0021;
|
|
|
|
// RFC NetBIOS encoded name length
|
|
|
|
public static final int NAME_LEN = 32;
|
|
|
|
// NetBIOS name classes
|
|
|
|
public static final int NAME_CLASS_IN = 0x0001;
|
|
|
|
// Bit shifts for opcode/flags values
|
|
|
|
private static final int SHIFT_FLAGS = 4;
|
|
private static final int SHIFT_OPCODE = 11;
|
|
|
|
// Default NetBIOS buffer size to allocate
|
|
|
|
public static final int DEFAULT_BUFSIZE = 1024;
|
|
|
|
// NetBIOS packet offsets
|
|
|
|
private static final int NB_TRANSID = 0;
|
|
private static final int NB_OPCODE = 2;
|
|
private static final int NB_QDCOUNT = 4;
|
|
private static final int NB_ANCOUNT = 6;
|
|
private static final int NB_NSCOUNT = 8;
|
|
private static final int NB_ARCOUNT = 10;
|
|
private static final int NB_DATA = 12;
|
|
|
|
// NetBIOS name registration error reponse codes (RCODE field)
|
|
|
|
public static final int FMT_ERR = 0x01;
|
|
public static final int SRV_ERR = 0x02;
|
|
public static final int IMP_ERR = 0x04;
|
|
public static final int RFS_ERR = 0x05;
|
|
public static final int ACT_ERR = 0x06;
|
|
public static final int CFT_ERR = 0x07;
|
|
|
|
// Name flags
|
|
|
|
public static final int NAME_PERM = 0x02;
|
|
public static final int NAME_ACTIVE = 0x04;
|
|
public static final int NAME_CONFLICT = 0x08;
|
|
public static final int NAME_DEREG = 0x10;
|
|
public static final int NAME_GROUP = 0x80;
|
|
|
|
// NetBIOS packet buffer
|
|
|
|
private byte[] m_nbbuf;
|
|
|
|
// Actual used packet length
|
|
|
|
private int m_datalen;
|
|
|
|
/**
|
|
* Default constructor
|
|
*/
|
|
public NetBIOSPacket()
|
|
{
|
|
m_nbbuf = new byte[DEFAULT_BUFSIZE];
|
|
m_datalen = NB_DATA;
|
|
}
|
|
|
|
/**
|
|
* Create a NetBIOS packet with the specified buffer.
|
|
*
|
|
* @param buf byte[]
|
|
*/
|
|
public NetBIOSPacket(byte[] buf)
|
|
{
|
|
m_nbbuf = buf;
|
|
m_datalen = NB_DATA;
|
|
}
|
|
|
|
/**
|
|
* Create a NetBIOS packet with the specified buffer size.
|
|
*
|
|
* @param siz int
|
|
*/
|
|
public NetBIOSPacket(int siz)
|
|
{
|
|
m_nbbuf = new byte[siz];
|
|
m_datalen = NB_DATA;
|
|
}
|
|
|
|
/**
|
|
* Dump the packet structure to the console.
|
|
*
|
|
* @param sessPkt True if this is a NetBIOS session packet, else false.
|
|
*/
|
|
public void DumpPacket(boolean sessPkt)
|
|
{
|
|
|
|
// Display the transaction id
|
|
|
|
logger.debug("NetBIOS Packet Dump :-");
|
|
|
|
// Detrmine the packet type
|
|
|
|
if (sessPkt == true)
|
|
{
|
|
|
|
switch (getPacketType())
|
|
{
|
|
|
|
// NetBIOS session request
|
|
|
|
case RFCNetBIOSProtocol.SESSION_REQUEST:
|
|
StringBuffer name = new StringBuffer();
|
|
for (int i = 0; i < 32; i++)
|
|
name.append((char) m_nbbuf[39 + i]);
|
|
logger.debug("Session request from " + NetBIOSSession.DecodeName(name.toString()));
|
|
break;
|
|
|
|
// NetBIOS message
|
|
|
|
case RFCNetBIOSProtocol.SESSION_MESSAGE:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Display the packet type
|
|
|
|
logger.debug(" Transaction Id : " + getTransactionId());
|
|
|
|
String opCode = null;
|
|
|
|
switch (getOpcode())
|
|
{
|
|
case NAME_QUERY:
|
|
opCode = "QUERY";
|
|
break;
|
|
case RESP_QUERY:
|
|
opCode = "QUERY (Response)";
|
|
break;
|
|
case NAME_REGISTER:
|
|
opCode = "NAME REGISTER";
|
|
break;
|
|
case RESP_REGISTER:
|
|
opCode = "NAME REGISTER (Response)";
|
|
break;
|
|
case NAME_RELEASE:
|
|
opCode = "NAME RELEASE";
|
|
break;
|
|
case RESP_RELEASE:
|
|
opCode = "NAME RELEASE (Response)";
|
|
break;
|
|
case WACK:
|
|
opCode = "WACK";
|
|
break;
|
|
case REFRESH:
|
|
opCode = "REFRESH";
|
|
break;
|
|
default:
|
|
opCode = Integer.toHexString(getOpcode());
|
|
break;
|
|
}
|
|
logger.debug(" Opcode : " + opCode);
|
|
|
|
// Display the flags
|
|
|
|
logger.debug(" Flags : " + Integer.toHexString(getFlags()));
|
|
|
|
// Display the name counts
|
|
|
|
logger.debug(" QDCount : " + getQuestionCount());
|
|
logger.debug(" ANCount : " + getAnswerCount());
|
|
logger.debug(" NSCount : " + getNameServiceCount());
|
|
logger.debug(" ARCount : " + getAdditionalCount());
|
|
|
|
// Dump the question name, if there is one
|
|
|
|
if (getQuestionCount() > 0)
|
|
{
|
|
|
|
// Get the encoded name string
|
|
|
|
StringBuffer encName = new StringBuffer();
|
|
for (int i = 1; i <= 32; i++)
|
|
encName.append((char) m_nbbuf[NB_DATA + i]);
|
|
|
|
// Decode the name
|
|
|
|
String name = NetBIOSSession.DecodeName(encName.toString());
|
|
logger.debug(" QName : " + name + " <" + NetBIOSName.TypeAsString(name.charAt(15)) + ">");
|
|
}
|
|
}
|
|
|
|
// Dump the raw data
|
|
|
|
logger.debug("********** Raw NetBIOS Data Dump **********");
|
|
HexDump.Dump(getBuffer(), getLength(), 0);
|
|
}
|
|
|
|
/**
|
|
* Get the additional byte count.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getAdditionalCount()
|
|
{
|
|
return DataPacker.getShort(m_nbbuf, NB_ARCOUNT);
|
|
}
|
|
|
|
/**
|
|
* Get the answer name details
|
|
*
|
|
* @return String
|
|
*/
|
|
public final String getAnswerName()
|
|
{
|
|
|
|
// Pack the encoded name into the NetBIOS packet
|
|
|
|
return NetBIOSSession.DecodeName(m_nbbuf, NB_DATA + 1);
|
|
}
|
|
|
|
/**
|
|
* Get the answer count.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getAnswerCount()
|
|
{
|
|
return DataPacker.getShort(m_nbbuf, NB_ANCOUNT);
|
|
}
|
|
|
|
/**
|
|
* Get the answer name list
|
|
*
|
|
* @return NetBIOSNameList
|
|
*/
|
|
public final NetBIOSNameList getAnswerNameList()
|
|
{
|
|
|
|
// Check if there are any answer names
|
|
|
|
int cnt = getAnswerCount();
|
|
if (cnt == 0)
|
|
return null;
|
|
|
|
NetBIOSNameList nameList = new NetBIOSNameList();
|
|
int pos = NB_DATA;
|
|
|
|
while (cnt-- > 0)
|
|
{
|
|
|
|
// Get a NetBIOS name from the buffer
|
|
|
|
int nameLen = NetBIOSName.decodeNetBIOSNameLength(m_nbbuf, pos);
|
|
NetBIOSName name = NetBIOSName.decodeNetBIOSName(m_nbbuf, pos);
|
|
|
|
// Skip the type, class and TTL
|
|
|
|
pos += nameLen;
|
|
pos += 8;
|
|
|
|
// Get the count of data bytes
|
|
|
|
int dataCnt = DataPacker.getShort(m_nbbuf, pos);
|
|
pos += 2;
|
|
|
|
while (dataCnt > 0)
|
|
{
|
|
|
|
// Get the flags, check if the name is a unique or group name
|
|
|
|
int flags = DataPacker.getShort(m_nbbuf, pos);
|
|
pos += 2;
|
|
if ((flags & NAME_GROUP) != 0)
|
|
name.setGroup(true);
|
|
|
|
// Get the IP address and add to the list of addresses for the current name
|
|
|
|
byte[] ipaddr = new byte[4];
|
|
for (int i = 0; i < 4; i++)
|
|
ipaddr[i] = m_nbbuf[pos++];
|
|
|
|
name.addIPAddress(ipaddr);
|
|
|
|
// Update the data count
|
|
|
|
dataCnt -= 6;
|
|
}
|
|
|
|
// Add the name to the name list
|
|
|
|
nameList.addName(name);
|
|
}
|
|
|
|
// Return the name list
|
|
|
|
return nameList;
|
|
}
|
|
|
|
/**
|
|
* Get the answer name list from an adapter status reply
|
|
*
|
|
* @return NetBIOSNameList
|
|
*/
|
|
public final NetBIOSNameList getAdapterStatusNameList()
|
|
{
|
|
|
|
// Check if there are any answer names
|
|
|
|
int cnt = getAnswerCount();
|
|
if (cnt == 0)
|
|
return null;
|
|
|
|
NetBIOSNameList nameList = new NetBIOSNameList();
|
|
int pos = NB_DATA;
|
|
|
|
// Skip the initial name
|
|
|
|
int nameLen = (int) (m_nbbuf[pos++] & 0xFF);
|
|
pos += nameLen;
|
|
pos = DataPacker.wordAlign(pos);
|
|
pos += 8;
|
|
|
|
// Get the count of data bytes and name count
|
|
|
|
int dataCnt = DataPacker.getShort(m_nbbuf, pos);
|
|
pos += 2;
|
|
|
|
int nameCnt = (int) (m_nbbuf[pos++] & 0xFF);
|
|
|
|
while (nameCnt > 0 && dataCnt > 0)
|
|
{
|
|
|
|
// Get the NetBIOS name/type
|
|
|
|
NetBIOSName nbName = new NetBIOSName(m_nbbuf, pos);
|
|
pos += 16;
|
|
|
|
// Get the name type flags, check if this is a unique or group name
|
|
|
|
int typ = DataPacker.getShort(m_nbbuf, pos);
|
|
pos += 2;
|
|
|
|
if ((typ & NAME_GROUP) != 0)
|
|
nbName.setGroup(true);
|
|
|
|
// Add the name to the list
|
|
|
|
nameList.addName(nbName);
|
|
|
|
// Update the data count and name count
|
|
|
|
dataCnt -= 18;
|
|
nameCnt--;
|
|
}
|
|
|
|
// Return the name list
|
|
|
|
return nameList;
|
|
}
|
|
|
|
/**
|
|
* Return the NetBIOS buffer.
|
|
*
|
|
* @return byte[]
|
|
*/
|
|
public final byte[] getBuffer()
|
|
{
|
|
return m_nbbuf;
|
|
}
|
|
|
|
/**
|
|
* Get the flags from the received NetBIOS packet.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getFlags()
|
|
{
|
|
int flags = DataPacker.getShort(m_nbbuf, NB_QDCOUNT) & MASK_NMFLAGS;
|
|
flags = flags >> SHIFT_FLAGS;
|
|
return flags;
|
|
}
|
|
|
|
/**
|
|
* Return the NetBIOS header flags value.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getHeaderFlags()
|
|
{
|
|
return m_nbbuf[1] & 0x00FF;
|
|
}
|
|
|
|
/**
|
|
* Return the NetBIOS header data length value.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getHeaderLength()
|
|
{
|
|
return DataPacker.getIntelShort(m_nbbuf, 2) & 0xFFFF;
|
|
}
|
|
|
|
/**
|
|
* Return the NetBIOS header message type.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getHeaderType()
|
|
{
|
|
return m_nbbuf[0] & 0x00FF;
|
|
}
|
|
|
|
/**
|
|
* Return the received packet length.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getLength()
|
|
{
|
|
return m_datalen;
|
|
}
|
|
|
|
/**
|
|
* Return the name service count.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getNameServiceCount()
|
|
{
|
|
return DataPacker.getShort(m_nbbuf, NB_NSCOUNT);
|
|
}
|
|
|
|
/**
|
|
* Return the NetBIOS opcode.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getOpcode()
|
|
{
|
|
int op = DataPacker.getShort(m_nbbuf, NB_OPCODE) & MASK_OPCODE;
|
|
op = op >> SHIFT_OPCODE;
|
|
return op;
|
|
}
|
|
|
|
/**
|
|
* Return the NetBIOS packet type.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getPacketType()
|
|
{
|
|
return (int) (m_nbbuf[0] & 0xFF);
|
|
}
|
|
|
|
/**
|
|
* Return the question count.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getQuestionCount()
|
|
{
|
|
return DataPacker.getShort(m_nbbuf, NB_QDCOUNT);
|
|
}
|
|
|
|
/**
|
|
* Get the question name.
|
|
*/
|
|
public final String getQuestionName()
|
|
{
|
|
|
|
// Pack the encoded name into the NetBIOS packet
|
|
|
|
return NetBIOSSession.DecodeName(m_nbbuf, NB_DATA + 1);
|
|
}
|
|
|
|
/**
|
|
* Get the question name length.
|
|
*/
|
|
public final int getQuestionNameLength()
|
|
{
|
|
|
|
// Pack the encoded name into the NetBIOS packet
|
|
|
|
return (int) m_nbbuf[NB_DATA] & 0xFF;
|
|
}
|
|
|
|
/**
|
|
* Return the result code for the received packet.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getResultCode()
|
|
{
|
|
int res = DataPacker.getShort(m_nbbuf, NB_OPCODE) & MASK_RCODE;
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Return the NetBIOS transaction id.
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getTransactionId()
|
|
{
|
|
return DataPacker.getShort(m_nbbuf, NB_TRANSID);
|
|
}
|
|
|
|
/**
|
|
* Determine if the received packet is a repsonse packet.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public final boolean isResponse()
|
|
{
|
|
if ((getOpcode() & MASK_RESPONSE) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Set the additional byte count.
|
|
*
|
|
* @param cnt int
|
|
*/
|
|
public final void setAdditionalCount(int cnt)
|
|
{
|
|
DataPacker.putShort((short) cnt, m_nbbuf, NB_ARCOUNT);
|
|
}
|
|
|
|
/**
|
|
* Set the answer byte count.
|
|
*
|
|
* @param cnt int
|
|
*/
|
|
public final void setAnswerCount(int cnt)
|
|
{
|
|
DataPacker.putShort((short) cnt, m_nbbuf, NB_ANCOUNT);
|
|
}
|
|
|
|
/**
|
|
* Set the answer name.
|
|
*
|
|
* @param name java.lang.String
|
|
* @param qtyp int
|
|
* @param qcls int
|
|
*/
|
|
public final int setAnswerName(String name, char ntyp, int qtyp, int qcls)
|
|
{
|
|
|
|
// RFC encode the NetBIOS name string
|
|
|
|
String encName = NetBIOSSession.ConvertName(name, ntyp);
|
|
byte[] nameByts = encName.getBytes();
|
|
|
|
// Pack the encoded name into the NetBIOS packet
|
|
|
|
int pos = NB_DATA;
|
|
m_nbbuf[pos++] = (byte) NAME_LEN;
|
|
|
|
for (int i = 0; i < 32; i++)
|
|
m_nbbuf[pos++] = nameByts[i];
|
|
m_nbbuf[pos++] = 0x00;
|
|
|
|
// Set the name type and class
|
|
|
|
DataPacker.putShort((short) qtyp, m_nbbuf, pos);
|
|
pos += 2;
|
|
|
|
DataPacker.putShort((short) qcls, m_nbbuf, pos);
|
|
pos += 2;
|
|
|
|
// Set the packet length
|
|
|
|
if (pos > m_datalen)
|
|
setLength(pos);
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Set the flags.
|
|
*
|
|
* @param flg int
|
|
*/
|
|
public final void setFlags(int flg)
|
|
{
|
|
int val = DataPacker.getShort(m_nbbuf, NB_OPCODE) & MASK_NOFLAGS;
|
|
val += (flg << SHIFT_FLAGS);
|
|
DataPacker.putShort((short) val, m_nbbuf, NB_OPCODE);
|
|
}
|
|
|
|
/**
|
|
* Set the NetBIOS packet header flags value.
|
|
*
|
|
* @param flg int
|
|
*/
|
|
public final void setHeaderFlags(int flg)
|
|
{
|
|
m_nbbuf[1] = (byte) (flg & 0x00FF);
|
|
}
|
|
|
|
/**
|
|
* Set the NetBIOS packet data length in the packet header.
|
|
*
|
|
* @param len int
|
|
*/
|
|
public final void setHeaderLength(int len)
|
|
{
|
|
DataPacker.putIntelShort(len, m_nbbuf, 2);
|
|
}
|
|
|
|
/**
|
|
* Set the NetBIOS packet type in the packet header.
|
|
*
|
|
* @param typ int
|
|
*/
|
|
public final void setHeaderType(int typ)
|
|
{
|
|
m_nbbuf[0] = (byte) (typ & 0x00FF);
|
|
}
|
|
|
|
/**
|
|
* Set the IP address.
|
|
*
|
|
* @return int
|
|
* @param off int
|
|
* @param ipaddr byte[]
|
|
*/
|
|
public final int setIPAddress(int off, byte[] ipaddr)
|
|
{
|
|
|
|
// Pack the IP address
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
m_nbbuf[off + i] = ipaddr[i];
|
|
|
|
// Set the packet length
|
|
|
|
int pos = off + 4;
|
|
if (pos > m_datalen)
|
|
setLength(pos);
|
|
|
|
// Return the new packet offset
|
|
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Set the packet data length.
|
|
*
|
|
* @param len int
|
|
*/
|
|
public final void setLength(int len)
|
|
{
|
|
m_datalen = len;
|
|
}
|
|
|
|
/**
|
|
* Set the name registration flags.
|
|
*
|
|
* @return int
|
|
* @param off int
|
|
* @param flg int
|
|
*/
|
|
public final int setNameRegistrationFlags(int off, int flg)
|
|
{
|
|
|
|
// Set the name registration flags
|
|
|
|
DataPacker.putShort((short) 0x0006, m_nbbuf, off);
|
|
DataPacker.putShort((short) flg, m_nbbuf, off + 2);
|
|
|
|
// Set the packet length
|
|
|
|
int pos = off + 4;
|
|
if (pos > m_datalen)
|
|
setLength(pos);
|
|
|
|
// Return the new packet offset
|
|
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Set the name service count.
|
|
*
|
|
* @param cnt int
|
|
*/
|
|
public final void setNameServiceCount(int cnt)
|
|
{
|
|
DataPacker.putShort((short) cnt, m_nbbuf, NB_NSCOUNT);
|
|
}
|
|
|
|
/**
|
|
* Set the NetBIOS opcode.
|
|
*
|
|
* @param op int
|
|
*/
|
|
public final void setOpcode(int op)
|
|
{
|
|
int val = DataPacker.getShort(m_nbbuf, NB_OPCODE) & MASK_NOOPCODE;
|
|
val = val + (op << SHIFT_OPCODE);
|
|
DataPacker.putShort((short) val, m_nbbuf, NB_OPCODE);
|
|
}
|
|
|
|
/**
|
|
* Set the question count.
|
|
*
|
|
* @param cnt int
|
|
*/
|
|
public final void setQuestionCount(int cnt)
|
|
{
|
|
DataPacker.putShort((short) cnt, m_nbbuf, NB_QDCOUNT);
|
|
}
|
|
|
|
/**
|
|
* Set the question name.
|
|
*
|
|
* @param name NetBIOSName
|
|
* @param qtyp int
|
|
* @param qcls int
|
|
* @return int
|
|
*/
|
|
public final int setQuestionName(NetBIOSName name, int qtyp, int qcls)
|
|
{
|
|
|
|
// Encode the NetBIOS name
|
|
|
|
byte[] nameByts = name.encodeName();
|
|
|
|
// Pack the encoded name into the NetBIOS packet
|
|
|
|
int pos = NB_DATA;
|
|
System.arraycopy(nameByts, 0, m_nbbuf, pos, nameByts.length);
|
|
pos += nameByts.length;
|
|
|
|
// Set the name type and class
|
|
|
|
DataPacker.putShort((short) qtyp, m_nbbuf, pos);
|
|
pos += 2;
|
|
|
|
DataPacker.putShort((short) qcls, m_nbbuf, pos);
|
|
pos += 2;
|
|
|
|
// Set the packet length
|
|
|
|
if (pos > m_datalen)
|
|
setLength(pos);
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Set the question name.
|
|
*
|
|
* @param name java.lang.String
|
|
* @param qtyp int
|
|
* @param qcls int
|
|
*/
|
|
public final int setQuestionName(String name, char ntyp, int qtyp, int qcls)
|
|
{
|
|
|
|
// RFC encode the NetBIOS name string
|
|
|
|
String encName = NetBIOSSession.ConvertName(name, ntyp);
|
|
byte[] nameByts = encName.getBytes();
|
|
|
|
// Pack the encoded name into the NetBIOS packet
|
|
|
|
int pos = NB_DATA;
|
|
m_nbbuf[pos++] = (byte) NAME_LEN;
|
|
|
|
for (int i = 0; i < 32; i++)
|
|
m_nbbuf[pos++] = nameByts[i];
|
|
m_nbbuf[pos++] = 0x00;
|
|
|
|
// Set the name type and class
|
|
|
|
DataPacker.putShort((short) qtyp, m_nbbuf, pos);
|
|
pos += 2;
|
|
|
|
DataPacker.putShort((short) qcls, m_nbbuf, pos);
|
|
pos += 2;
|
|
|
|
// Set the packet length
|
|
|
|
if (pos > m_datalen)
|
|
setLength(pos);
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Pack the resource data into the packet.
|
|
*
|
|
* @return int
|
|
* @param off int
|
|
* @param flg int
|
|
* @param data byte[]
|
|
* @param len int
|
|
*/
|
|
public final int setResourceData(int off, int flg, byte[] data, int len)
|
|
{
|
|
|
|
// Set the resource data type
|
|
|
|
DataPacker.putShort((short) flg, m_nbbuf, off);
|
|
|
|
// Pack the data
|
|
|
|
int pos = off + 2;
|
|
for (int i = 0; i < len; i++)
|
|
m_nbbuf[pos++] = data[i];
|
|
|
|
// Set the packet length
|
|
|
|
if (pos > m_datalen)
|
|
setLength(pos);
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Set the resource data length in the NetBIOS packet.
|
|
*
|
|
* @return int
|
|
* @param off int
|
|
* @param len int
|
|
*/
|
|
public final int setResourceDataLength(int off, int len)
|
|
{
|
|
|
|
// Set the resource data length
|
|
|
|
DataPacker.putShort((short) len, m_nbbuf, off);
|
|
|
|
// Set the packet length
|
|
|
|
int pos = off + 2;
|
|
if (pos > m_datalen)
|
|
setLength(pos);
|
|
|
|
// Return the new packet offset
|
|
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Set the resource record.
|
|
*
|
|
* @param pktoff Packet offset to pack the resource record.
|
|
* @param offset Offset to name.
|
|
* @param qtyp int
|
|
* @param qcls int
|
|
*/
|
|
public final int setResourceRecord(int pktoff, int rroff, int qtyp, int qcls)
|
|
{
|
|
|
|
// Pack the resource record details
|
|
|
|
DataPacker.putShort((short) (0xC000 + rroff), m_nbbuf, pktoff);
|
|
DataPacker.putShort((short) qtyp, m_nbbuf, pktoff + 2);
|
|
DataPacker.putShort((short) qcls, m_nbbuf, pktoff + 4);
|
|
|
|
// Set the packet length
|
|
|
|
int pos = pktoff + 6;
|
|
if (pos > m_datalen)
|
|
setLength(pos);
|
|
|
|
// Return the new packet offset
|
|
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Set the transaction id.
|
|
*
|
|
* @param id int
|
|
*/
|
|
public final void setTransactionId(int id)
|
|
{
|
|
DataPacker.putShort((short) id, m_nbbuf, NB_TRANSID);
|
|
}
|
|
|
|
/**
|
|
* Set the time to live for the packet.
|
|
*
|
|
* @return int
|
|
* @param off int
|
|
* @param ttl int
|
|
*/
|
|
public final int setTTL(int off, int ttl)
|
|
{
|
|
|
|
// Set the time to live value for the packet
|
|
|
|
DataPacker.putInt(ttl, m_nbbuf, off);
|
|
|
|
// Set the packet length
|
|
|
|
int pos = off + 4;
|
|
if (pos > m_datalen)
|
|
setLength(pos);
|
|
|
|
// Return the new packet offset
|
|
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Return a packet type as a string
|
|
*
|
|
* @param typ int
|
|
* @return String
|
|
*/
|
|
public final static String getTypeAsString(int typ)
|
|
{
|
|
|
|
// Return the NetBIOS packet type as a string
|
|
|
|
String typStr = "";
|
|
|
|
switch (typ)
|
|
{
|
|
case RFCNetBIOSProtocol.SESSION_ACK:
|
|
typStr = "SessionAck";
|
|
break;
|
|
case RFCNetBIOSProtocol.SESSION_KEEPALIVE:
|
|
typStr = "SessionKeepAlive";
|
|
break;
|
|
case RFCNetBIOSProtocol.SESSION_MESSAGE:
|
|
typStr = "SessionMessage";
|
|
break;
|
|
case RFCNetBIOSProtocol.SESSION_REJECT:
|
|
typStr = "SessionReject";
|
|
break;
|
|
case RFCNetBIOSProtocol.SESSION_REQUEST:
|
|
typStr = "SessionRequest";
|
|
break;
|
|
case RFCNetBIOSProtocol.SESSION_RETARGET:
|
|
typStr = "SessionRetarget";
|
|
break;
|
|
default:
|
|
typStr = "Unknown 0x" + Integer.toHexString(typ);
|
|
break;
|
|
}
|
|
|
|
// Return the packet type string
|
|
|
|
return typStr;
|
|
}
|
|
|
|
/**
|
|
* Build a name query response packet for the specified NetBIOS name
|
|
*
|
|
* @param name NetBIOSName
|
|
* @return int
|
|
*/
|
|
public final int buildNameQueryResponse(NetBIOSName name)
|
|
{
|
|
|
|
// Fill in the header
|
|
|
|
setOpcode(NetBIOSPacket.RESP_QUERY);
|
|
setFlags(NetBIOSPacket.FLG_RECURSDES + NetBIOSPacket.FLG_AUTHANSWER);
|
|
|
|
setQuestionCount(0);
|
|
setAnswerCount(1);
|
|
setAdditionalCount(0);
|
|
setNameServiceCount(0);
|
|
|
|
int pos = setAnswerName(name.getName(), name.getType(), 0x20, 0x01);
|
|
pos = setTTL(pos, 10000);
|
|
pos = setResourceDataLength(pos, name.numberOfAddresses() * 6);
|
|
|
|
// Pack the IP address(es) for this name
|
|
|
|
for (int i = 0; i < name.numberOfAddresses(); i++)
|
|
{
|
|
|
|
// Get the current IP address
|
|
|
|
byte[] ipaddr = name.getIPAddress(i);
|
|
|
|
// Pack the NetBIOS flags and IP address
|
|
|
|
DataPacker.putShort((short) 0x00, m_nbbuf, pos);
|
|
pos += 2;
|
|
|
|
for (int j = 0; j < 4; j++)
|
|
m_nbbuf[pos++] = ipaddr[j];
|
|
}
|
|
|
|
// Set the packet length, and return the length
|
|
|
|
setLength(pos);
|
|
return getLength();
|
|
}
|
|
|
|
/**
|
|
* Build an add name request packet for the specified NetBIOS name
|
|
*
|
|
* @param name NetBIOSName
|
|
* @param addrIdx int
|
|
* @param tranId int
|
|
* @return int
|
|
*/
|
|
public final int buildAddNameRequest(NetBIOSName name, int addrIdx, int tranId)
|
|
{
|
|
|
|
// Initialize an add name NetBIOS packet
|
|
|
|
setTransactionId(tranId);
|
|
setOpcode(NetBIOSPacket.NAME_REGISTER);
|
|
setFlags(NetBIOSPacket.FLG_BROADCAST + NetBIOSPacket.FLG_RECURSION);
|
|
|
|
setQuestionCount(1);
|
|
setAnswerCount(0);
|
|
setNameServiceCount(0);
|
|
setAdditionalCount(1);
|
|
|
|
int pos = setQuestionName(name.getName(), name.getType(), 0x20, 0x01);
|
|
pos = setResourceRecord(pos, 12, 0x20, 0x01);
|
|
|
|
if (name.getTimeToLive() == 0)
|
|
pos = setTTL(pos, NetBIOSName.DefaultTTL);
|
|
else
|
|
pos = setTTL(pos, name.getTimeToLive());
|
|
|
|
short flg = 0;
|
|
if (name.isGroupName())
|
|
flg = (short) 0x8000;
|
|
pos = setNameRegistrationFlags(pos, flg);
|
|
pos = setIPAddress(pos, name.getIPAddress(addrIdx));
|
|
|
|
// Return the packet length
|
|
|
|
setLength(pos);
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Build a refresh name request packet for the specified NetBIOS name
|
|
*
|
|
* @param name NetBIOSName
|
|
* @param addrIdx int
|
|
* @param tranId int
|
|
* @return int
|
|
*/
|
|
public final int buildRefreshNameRequest(NetBIOSName name, int addrIdx, int tranId)
|
|
{
|
|
|
|
// Initialize an add name NetBIOS packet
|
|
|
|
setTransactionId(tranId);
|
|
setOpcode(NetBIOSPacket.REFRESH);
|
|
setFlags(NetBIOSPacket.FLG_BROADCAST + NetBIOSPacket.FLG_RECURSION);
|
|
|
|
setQuestionCount(1);
|
|
setAnswerCount(0);
|
|
setNameServiceCount(0);
|
|
setAdditionalCount(1);
|
|
|
|
int pos = setQuestionName(name.getName(), name.getType(), 0x20, 0x01);
|
|
pos = setResourceRecord(pos, 12, 0x20, 0x01);
|
|
|
|
if (name.getTimeToLive() == 0)
|
|
pos = setTTL(pos, NetBIOSName.DefaultTTL);
|
|
else
|
|
pos = setTTL(pos, name.getTimeToLive());
|
|
|
|
short flg = 0;
|
|
if (name.isGroupName())
|
|
flg = (short) 0x8000;
|
|
pos = setNameRegistrationFlags(pos, flg);
|
|
pos = setIPAddress(pos, name.getIPAddress(addrIdx));
|
|
|
|
// Return the packet length
|
|
|
|
setLength(pos);
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Build a delete name request packet for the specified NetBIOS name
|
|
*
|
|
* @param name NetBIOSName
|
|
* @param addrIdx int
|
|
* @param tranId int
|
|
* @return int
|
|
*/
|
|
public final int buildDeleteNameRequest(NetBIOSName name, int addrIdx, int tranId)
|
|
{
|
|
|
|
// Initialize a delete name NetBIOS packet
|
|
|
|
setTransactionId(tranId);
|
|
setOpcode(NetBIOSPacket.NAME_RELEASE);
|
|
setFlags(NetBIOSPacket.FLG_BROADCAST + NetBIOSPacket.FLG_RECURSION);
|
|
|
|
setQuestionCount(1);
|
|
setAnswerCount(0);
|
|
setNameServiceCount(0);
|
|
setAdditionalCount(1);
|
|
|
|
int pos = setQuestionName(name.getName(), name.getType(), 0x20, 0x01);
|
|
pos = setResourceRecord(pos, 12, 0x20, 0x01);
|
|
pos = setTTL(pos, 30000);
|
|
|
|
short flg = 0;
|
|
if (name.isGroupName())
|
|
flg = (short) 0x8000;
|
|
pos = setNameRegistrationFlags(pos, flg);
|
|
pos = setIPAddress(pos, name.getIPAddress(addrIdx));
|
|
|
|
// Return the packet length
|
|
|
|
setLength(pos);
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Build a name quesy request packet for the specified NetBIOS name
|
|
*
|
|
* @param name NetBIOSName
|
|
* @param tranId int
|
|
* @return int
|
|
*/
|
|
public final int buildNameQueryRequest(NetBIOSName name, int tranId)
|
|
{
|
|
|
|
// Initialize a name query NetBIOS packet
|
|
|
|
setTransactionId(tranId);
|
|
setOpcode(NetBIOSPacket.NAME_QUERY);
|
|
setFlags(NetBIOSSession.hasWINSServer() ? 0 : NetBIOSPacket.FLG_BROADCAST);
|
|
setQuestionCount(1);
|
|
return setQuestionName(name, NetBIOSPacket.NAME_TYPE_NB, NetBIOSPacket.NAME_CLASS_IN);
|
|
}
|
|
|
|
/**
|
|
* Build a session setup request packet
|
|
*
|
|
* @param fromName NetBIOSName
|
|
* @param toName NetBIOSName
|
|
* @return int
|
|
*/
|
|
public final int buildSessionSetupRequest(NetBIOSName fromName, NetBIOSName toName)
|
|
{
|
|
|
|
// Initialize the session setup packet header
|
|
|
|
m_nbbuf[0] = (byte) RFCNetBIOSProtocol.SESSION_REQUEST;
|
|
m_nbbuf[1] = (byte) 0; // flags
|
|
|
|
// Set the remote NetBIOS name
|
|
|
|
int pos = 4;
|
|
byte[] encToName = toName.encodeName();
|
|
System.arraycopy(encToName, 0, m_nbbuf, pos, encToName.length);
|
|
pos += encToName.length;
|
|
|
|
// Set the local NetBIOS name
|
|
|
|
byte[] encFromName = fromName.encodeName();
|
|
System.arraycopy(encFromName, 0, m_nbbuf, pos, encFromName.length);
|
|
pos += encFromName.length;
|
|
|
|
// Set the packet length
|
|
|
|
setLength(pos);
|
|
|
|
// Set the length in the session request header
|
|
|
|
DataPacker.putShort((short) (pos - RFCNetBIOSProtocol.HEADER_LEN), m_nbbuf, 2);
|
|
|
|
// Return the packet length
|
|
|
|
return pos;
|
|
}
|
|
} |