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

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;
}
}