/*
* Copyright (C) 2006-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.jlan.server.auth.passthru;
import java.io.IOException;
import org.alfresco.jlan.netbios.NetBIOSSession;
import org.alfresco.jlan.netbios.NetworkSession;
import org.alfresco.jlan.netbios.RFCNetBIOSProtocol;
import org.alfresco.jlan.smb.PacketType;
import org.alfresco.jlan.smb.SMBException;
import org.alfresco.jlan.smb.SMBStatus;
import org.alfresco.jlan.util.DataPacker;
/**
* SMB packet type class
*
* @author gkspencer
*/
public class SMBPacket {
// SMB packet offsets, assuming an RFC NetBIOS transport
public static final int SIGNATURE = RFCNetBIOSProtocol.HEADER_LEN;
public static final int COMMAND = 4 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int ERRORCODE = 5 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int ERRORCLASS = 5 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int ERROR = 7 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int FLAGS = 9 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int FLAGS2 = 10 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int PIDHIGH = 12 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int SID = 18 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int SEQNO = 20 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int TID = 24 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int PID = 26 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int UID = 28 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int MID = 30 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int WORDCNT = 32 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int ANDXCOMMAND = 33 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int ANDXRESERVED = 34 + RFCNetBIOSProtocol.HEADER_LEN;
public static final int PARAMWORDS = 33 + RFCNetBIOSProtocol.HEADER_LEN;
// SMB packet header length for a transaction type request
public static final int TRANS_HEADERLEN = 66 + RFCNetBIOSProtocol.HEADER_LEN;
// Minimum receive length for a valid SMB packet
public static final int MIN_RXLEN = 32;
// Default buffer size to allocate for SMB packets
public static final int DEFAULT_BUFSIZE = 4096;
// Flag bits
public static final int FLG_SUBDIALECT = 0x01;
public static final int FLG_CASELESS = 0x08;
public static final int FLG_CANONICAL = 0x10;
public static final int FLG_OPLOCK = 0x20;
public static final int FLG_NOTIFY = 0x40;
public static final int FLG_RESPONSE = 0x80;
// Flag2 bits
public static final int FLG2_LONGFILENAMES = 0x0001;
public static final int FLG2_EXTENDEDATTRIB = 0x0002;
public static final int FLG2_SECURITYSIG = 0x0004;
public static final int FLG2_EXTENDEDSECURITY = 0x0800;
public static final int FLG2_READIFEXE = 0x2000;
public static final int FLG2_LONGERRORCODE = 0x4000;
public static final int FLG2_UNICODE = 0x8000;
// Security mode bits
public static final int SEC_USER = 0x0001;
public static final int SEC_ENCRYPT = 0x0002;
// Raw mode bits
public static final int RAW_READ = 0x0001;
public static final int RAW_WRITE = 0x0002;
// SMB packet buffer
private byte[] m_smbbuf;
// Packet type
private int m_pkttype;
// Current byte area pack/unpack position
protected int m_pos;
protected int m_endpos;
// Time of last packet send
protected long m_lastTxTime;
/**
* Default constructor
*/
public SMBPacket() {
m_smbbuf = new byte[DEFAULT_BUFSIZE];
InitializeBuffer();
}
/**
* Construct an SMB packet using the specified packet buffer.
*
* @param buf SMB packet buffer.
*/
public SMBPacket(byte[] buf) {
m_smbbuf = buf;
}
/**
* Construct an SMB packet of the specified size.
*
* @param siz Size of SMB packet buffer to allocate.
*/
public SMBPacket(int siz) {
m_smbbuf = new byte[siz];
InitializeBuffer();
}
/**
* Check if a received SMB is valid, if not then throw an exception
*
* @exception SMBException
*/
public final void checkForError()
throws SMBException {
// Check if a valid SMB response has been received
if (isValidResponse() == false) {
// Check for NT error codes
if ( isLongErrorCode())
throw new SMBException(SMBStatus.NTErr, getLongErrorCode());
else
throw new SMBException(getErrorClass(), getErrorCode());
}
}
/**
* Clear the data byte count
*/
public final void clearBytes() {
int offset = getByteOffset() - 2;
DataPacker.putIntelShort( 0, m_smbbuf, offset);
}
/**
* Check if the error class/code match the specified error/class
*
* @param errClass int
* @param errCode int
* @return boolean
*/
public final boolean equalsError(int errClass, int errCode) {
if ( getErrorClass() == errClass && getErrorCode() == errCode)
return true;
return false;
}
/**
* Send the SMB packet and receive the response packet
*
* @param sess Network session to send/receive the packet over.
* @param rxPkt SMB packet to receive the response into.
* @param throwerr If true then throw an I/O error if an invalid response is
* received.
* @exception java.io.IOException If a network error occurs.
* @exception SMBException If an SMB level error occurs
*/
protected final synchronized void ExchangeLowLevelSMB(NetworkSession sess, SMBPacket rxPkt, boolean throwerr)
throws java.io.IOException, SMBException {
// Set multiplex id
if ( getMultiplexId() == 0)
setMultiplexId(1);
// Send the SMB request
sess.Send(m_smbbuf, getLength());
// Receive a response
if (sess.Receive(rxPkt.getBuffer()) >= MIN_RXLEN) {
// Check if the response is for the current request
if ( rxPkt.getCommand() == m_pkttype) {
// Check if a valid SMB response has been received
if (throwerr == true)
checkForError();
// Valid packet received, return to caller
return;
}
}
// Invalid receive packet
throw new java.io.IOException("Invalid SMB Receive Packet");
}
/**
* Send/receive an SMB protocol packet to the remote server.
*
* @param sess SMB session to send/receive data on.
* @param rxPkt SMB packet to receive the response into.
* @exception java.io.IOException If an I/O error occurs.
* @exception SMBException If an SMB level error occurs.
*/
public synchronized final void ExchangeSMB( AuthenticateSession sess, SMBPacket rxPkt)
throws SMBException, IOException {
// Call the main SMB exhchange method
ExchangeSMB(sess, rxPkt, false);
}
/**
* Send the SMB packet and receive the response packet
*
* @param sess SMB session to send/receive the packet over.
* @param rxPkt SMB packet to receive the response into.
* @param throwerr If true then throw an I/O error if an invalid response is
* received.
* @exception java.io.IOException If an I/O error occurs.
* @exception SMBException If an SMB level error occurs.
*/
public synchronized final void ExchangeSMB( AuthenticateSession sess, SMBPacket rxPkt, boolean throwerr)
throws SMBException, IOException {
// Set the process id, user id and multiplex id
setProcessId(sess.getProcessId());
setUserId(sess.getUserId());
if ( getMultiplexId() == 0)
setMultiplexId(1);
// Get the network session
NetworkSession netSess = sess.getSession();
// Send the SMB request
netSess.Send(m_smbbuf, getLength());
// Receive the response, other asynchronous responses may be received before the response for this request
boolean rxValid = false;
while ( rxValid == false) {
// Receive a response
if (netSess.Receive(rxPkt.getBuffer()) >= MIN_RXLEN) {
// Check if the response is for the current request
if ( rxPkt.getCommand() == m_pkttype) {
// Check if a valid SMB response has been received
if (throwerr == true)
checkForError();
// Valid packet received, return to caller
return;
}
}
}
// Invalid receive packet
throw new java.io.IOException("Invalid SMB Receive Packet");
}
/**
* Get the secondary command code
*
* @return Secondary command code
*/
public final int getAndXCommand() {
return m_smbbuf[ANDXCOMMAND] & 0xFF;
}
/**
* Return the byte array used for the SMB packet
*
* @return Byte array used for the SMB packet.
*/
public final byte[] getBuffer() {
return m_smbbuf;
}
/**
* Return the total buffer size available to the SMB request
*
* @return Total SMB buffer length available.
*/
public final int getBufferLength() {
return m_smbbuf.length - RFCNetBIOSProtocol.HEADER_LEN;
}
/**
* Return the available buffer space for data bytes
*
* @return int
*/
public final int getAvailableLength() {
return m_smbbuf.length - DataPacker.longwordAlign(getByteOffset());
}
/**
* Get the data byte count for the SMB packet
*
* @return Data byte count
*/
public final int getByteCount() {
// Calculate the offset of the byte count
int pos = PARAMWORDS + (2 * getParameterCount());
return DataPacker.getIntelShort(m_smbbuf, pos);
}
/**
* Get the data byte area offset within the SMB packet
*
* @return Data byte offset within the SMB packet.
*/
public final int getByteOffset() {
// Calculate the offset of the byte buffer
int pCnt = getParameterCount();
int pos = WORDCNT + (2 * pCnt) + 3;
return pos;
}
/**
* Get the SMB command
*
* @return SMB command code.
*/
public final int getCommand() {
return m_smbbuf[COMMAND] & 0xFF;
}
/**
* Determine if normal or long error codes have been returned
*
* @return boolean
*/
public final boolean hasLongErrorCode() {
if ((getFlags2() & FLG2_LONGERRORCODE) == 0)
return false;
return true;
}
/**
* Return the saved packet type
*
* @return int
*/
public final int isType() {
return m_pkttype;
}
/**
* Check if the packet contains ASCII or Unicode strings
*
* @return boolean
*/
public final boolean isUnicode() {
return (getFlags2() & FLG2_UNICODE) != 0 ? true : false;
}
/**
* Check if the packet is using caseless filenames
*
* @return boolean
*/
public final boolean isCaseless() {
return (getFlags() & FLG_CASELESS) != 0 ? true : false;
}
/**
* Check if long file names are being used
*
* @return boolean
*/
public final boolean isLongFileNames() {
return (getFlags2() & FLG2_LONGFILENAMES) != 0 ? true : false;
}
/**
* Check if long error codes are being used
*
* @return boolean
*/
public final boolean isLongErrorCode() {
return (getFlags2() & FLG2_LONGERRORCODE) != 0 ? true : false;
}
/**
* Get the SMB error class
*
* @return SMB error class.
*/
public final int getErrorClass() {
return m_smbbuf[ERRORCLASS] & 0xFF;
}
/**
* Get the SMB error code
*
* @return SMB error code.
*/
public final int getErrorCode() {
return m_smbbuf[ERROR] & 0xFF;
}
/**
* Get the SMB flags value.
*
* @return SMB flags value.
*/
public final int getFlags() {
return m_smbbuf[FLAGS] & 0xFF;
}
/**
* Get the SMB flags2 value.
*
* @return SMB flags2 value.
*/
public final int getFlags2() {
return DataPacker.getIntelShort(m_smbbuf, FLAGS2);
}
/**
* Calculate the total used packet length.
*
* @return Total used packet length.
*/
public final int getLength() {
return (getByteOffset() + getByteCount()) - SIGNATURE;
}
/**
* Get the long SMB error code
*
* @return Long SMB error code.
*/
public final int getLongErrorCode() {
return DataPacker.getIntelInt(m_smbbuf, ERRORCODE);
}
/**
* Get the multiplex identifier.
*
* @return Multiplex identifier.
*/
public final int getMultiplexId() {
return DataPacker.getIntelShort(m_smbbuf, MID);
}
/**
* Get a parameter word from the SMB packet.
*
* @param idx Parameter index (zero based).
* @return Parameter word value.
* @exception java.lang.IndexOutOfBoundsException If the parameter index is out of range.
*/
public final int getParameter(int idx) throws java.lang.IndexOutOfBoundsException {
// Range check the parameter index
if (idx > getParameterCount())
throw new java.lang.IndexOutOfBoundsException();
// Calculate the parameter word offset
int pos = WORDCNT + (2 * idx) + 1;
return DataPacker.getIntelShort(m_smbbuf, pos) & 0xFFFF;
}
/**
* Get the specified parameter words, as an int value.
*
* @param idx Parameter index (zero based).
* @return int
*/
public final int getParameterLong(int idx) {
int pos = WORDCNT + (2 * idx) + 1;
return DataPacker.getIntelInt(m_smbbuf, pos);
}
/**
* Get the parameter count
*
* @return Parameter word count.
*/
public final int getParameterCount() {
return m_smbbuf[WORDCNT];
}
/**
* Get the process indentifier (PID)
*
* @return Process identifier value.
*/
public final int getProcessId() {
return DataPacker.getIntelShort(m_smbbuf, PID);
}
/**
* Get the tree identifier (TID)
*
* @return Tree identifier (TID)
*/
public final int getTreeId() {
return DataPacker.getIntelShort(m_smbbuf, TID);
}
/**
* Get the user identifier (UID)
*
* @return User identifier (UID)
*/
public final int getUserId() {
return DataPacker.getIntelShort(m_smbbuf, UID);
}
/**
* Return the last sent packet time
*
* @return long
*/
public final long getLastPacketSendTime() {
return m_lastTxTime;
}
/**
* Initialize the SMB packet buffer.
*/
private final void InitializeBuffer() {
// Set the packet signature
m_smbbuf[SIGNATURE] = (byte) 0xFF;
m_smbbuf[SIGNATURE + 1] = (byte) 'S';
m_smbbuf[SIGNATURE + 2] = (byte) 'M';
m_smbbuf[SIGNATURE + 3] = (byte) 'B';
}
/**
* Determine if this packet is an SMB response, or command packet
*
* @return true if this SMB packet is a response, else false
*/
public final boolean isResponse() {
int resp = getFlags();
if ((resp & FLG_RESPONSE) != 0)
return true;
return false;
}
/**
* Check if the response packet is valid, ie. type and flags
*
* @return true if the SMB packet is a response packet and the response is
* valid, else false.
*/
public final boolean isValidResponse() {
// Check if this is a response packet, and the correct type of packet
if (isResponse() && getCommand() == m_pkttype) {
// Check if standard error codes or NT 32-bit error codes are being used
if (( getFlags2() & FLG2_LONGERRORCODE) == 0) {
if ( getErrorCode() == SMBStatus.Success)
return true;
}
else if ( getLongErrorCode() == SMBStatus.NTSuccess)
return true;
}
return false;
}
/**
* Pack a byte (8 bit) value into the byte area
*
* @param val byte
*/
public final void packByte(byte val) {
m_smbbuf[m_pos++] = val;
}
/**
* Pack a byte (8 bit) value into the byte area
*
* @param val int
*/
public final void packByte(int val) {
m_smbbuf[m_pos++] = (byte) val;
}
/**
* Pack the specified bytes into the byte area
*
* @param byts byte[]
* @param len int
*/
public final void packBytes(byte[] byts, int len) {
System.arraycopy(byts,0,m_smbbuf,m_pos,len);
m_pos += len;
}
/**
* Pack a string using either ASCII or Unicode into the byte area
*
* @param str String
* @param uni boolean
*/
public final void packString(String str, boolean uni) {
// Check for Unicode or ASCII
if ( uni) {
// Word align the buffer position, pack the Unicode string
m_pos = DataPacker.wordAlign(m_pos);
DataPacker.putUnicodeString(str,m_smbbuf,m_pos,true);
m_pos += (str.length() * 2) + 2;
}
else {
// Pack the ASCII string
DataPacker.putString(str,m_smbbuf,m_pos,true);
m_pos += str.length() + 1;
}
}
/**
* Pack a word (16 bit) value into the byte area
*
* @param val int
*/
public final void packWord(int val) {
DataPacker.putIntelShort(val, m_smbbuf, m_pos);
m_pos += 2;
}
/**
* Pack a 32 bit integer value into the byte area
*
* @param val int
*/
public final void packInt(int val) {
DataPacker.putIntelInt(val,m_smbbuf,m_pos);
m_pos += 4;
}
/**
* Pack a long integer (64 bit) value into the byte area
*
* @param val long
*/
public final void packLong(long val) {
DataPacker.putIntelLong(val,m_smbbuf,m_pos);
m_pos += 8;
}
/**
* Return the current byte area buffer position
*
* @return int
*/
public final int getPosition() {
return m_pos;
}
/**
* Set the byte area buffer position
*
* @param pos int
*/
public final void setPosition(int pos) {
m_pos = pos;
}
/**
* Unpack a byte value from the byte area
*
* @return int
*/
public final int unpackByte() {
return (int) m_smbbuf[m_pos++];
}
/**
* Unpack a block of bytes from the byte area
*
* @param len int
* @return byte[]
*/
public final byte[] unpackBytes(int len) {
if ( len <= 0)
return null;
byte[] buf = new byte[len];
System.arraycopy(m_smbbuf,m_pos,buf,0,len);
m_pos += len;
return buf;
}
/**
* Unpack a word (16 bit) value from the byte area
*
* @return int
*/
public final int unpackWord() {
int val = DataPacker.getIntelShort(m_smbbuf,m_pos);
m_pos += 2;
return val;
}
/**
* Unpack an integer (32 bit) value from the byte/parameter area
*
* @return int
*/
public final int unpackInt() {
int val = DataPacker.getIntelInt(m_smbbuf,m_pos);
m_pos += 4;
return val;
}
/**
* Unpack a long integer (64 bit) value from the byte area
*
* @return long
*/
public final long unpackLong() {
long val = DataPacker.getIntelLong(m_smbbuf,m_pos);
m_pos += 8;
return val;
}
/**
* Unpack a string from the byte area
*
* @param uni boolean
* @return String
*/
public final String unpackString(boolean uni) {
// Check for Unicode or ASCII
String ret = null;
if ( uni) {
// Word align the current buffer position
m_pos = DataPacker.wordAlign(m_pos);
ret = DataPacker.getUnicodeString(m_smbbuf,m_pos,255);
if ( ret != null)
m_pos += ( ret.length() * 2) + 2;
}
else {
// Unpack the ASCII string
ret = DataPacker.getString(m_smbbuf,m_pos,255);
if ( ret != null)
m_pos += ret.length() + 1;
}
// Return the string
return ret;
}
/**
* Unpack a string from the byte area
*
* @param len int
* @param uni boolean
* @return String
*/
public final String unpackString(int len, boolean uni) {
// Check for Unicode or ASCII
String ret = null;
if ( uni) {
// Word align the current buffer position
m_pos = DataPacker.wordAlign(m_pos);
ret = DataPacker.getUnicodeString(m_smbbuf,m_pos,len);
if ( ret != null)
m_pos += ( ret.length() * 2);
}
else {
// Unpack the ASCII string
ret = DataPacker.getString(m_smbbuf,m_pos,len);
if ( ret != null)
m_pos += ret.length();
}
// Return the string
return ret;
}
/**
* Check if there is more data in the byte area
*
* @return boolean
*/
public final boolean hasMoreData() {
if ( m_pos < m_endpos)
return true;
return false;
}
/**
* Receive an SMB response packet.
*
* @param sess NetBIOS session to receive the SMB packet on.
* @exception java.io.IOException If an I/O error occurs.
*/
private final void ReceiveSMB(NetBIOSSession sess)
throws java.io.IOException {
if (sess.Receive(m_smbbuf) >= MIN_RXLEN)
return;
// Not enough data received for an SMB header
throw new java.io.IOException("Short NetBIOS receive");
}
/**
* Receive an SMB packet on the spceified SMB session.
*
* @param sess SMB session to receive the packet on.
* @exception java.io.IOException If a network error occurs
* @exception SMBException If an SMB level error occurs
*/
protected final void ReceiveSMB( AuthenticateSession sess)
throws java.io.IOException, SMBException {
// Call the main receive method
ReceiveSMB(sess, true);
}
/**
* Receive an SMB packet on the spceified SMB session.
*
* @param sess SMB session to receive the packet on.
* @param throwErr Flag to indicate if an error is thrown if an error response is received
* @exception java.io.IOException If a network error occurs
* @exception SMBException If an SMB level error occurs
*/
protected final void ReceiveSMB( AuthenticateSession sess, boolean throwErr)
throws java.io.IOException, SMBException {
// Get the network session
NetworkSession netSess= sess.getSession();
// Receive the response, other asynchronous responses may be received before the response for this request
boolean rxValid = false;
while ( rxValid == false) {
// Receive a response
if (netSess.Receive(getBuffer()) >= MIN_RXLEN) {
// Check if the response is for the current request
if ( getCommand() == m_pkttype) {
// Check if a valid SMB response has been received
if ( throwErr == true)
checkForError();
// Valid packet received, return to caller
return;
}
// Asynchronous response received, pass the packet to the session for processing
sess.processAsynchResponse(this);
}
else {
// Not enough data received for an SMB header
throw new java.io.IOException("Short NetBIOS receive");
}
}
}
/**
* Receive an asynchronous SMB response from the server
*
* @param sess Session
* @param waitTime Receive timeout in milliseconds, or zero for no timeout
* @throws java.io.IOException
* @throws SMBException
*/
protected final void ReceiveAsynchSMB( AuthenticateSession sess, int waitTime)
throws java.io.IOException, SMBException {
// Get the network session
NetworkSession netSess = sess.getSession();
netSess.setTimeout( waitTime);
// Receive, or wait for, a response
if (netSess.Receive(getBuffer()) >= MIN_RXLEN) {
// Asynchronous response received, pass the packet to the session for processing
sess.processAsynchResponse(this);
}
else {
// Not enough data received for an SMB header
throw new java.io.IOException("Short NetBIOS receive");
}
}
/**
* Send the SMB packet on the specified SMB session.
*
* @param sess SMB session to send this packet over.
* @exception java.io.IOException If an I/O error occurs.
*/
protected final void SendSMB( AuthenticateSession sess) throws java.io.IOException {
// Update the last send time
m_lastTxTime = System.currentTimeMillis();
// Send the SMB request
sess.getSession().Send(m_smbbuf, getLength());
}
/**
* Set the secondary SMB command
*
* @param cmd Secondary SMB command code.
*/
public final void setAndXCommand(int cmd) {
// Set the chained command packet type
m_smbbuf[ANDXCOMMAND] = (byte) cmd;
m_smbbuf[ANDXRESERVED] = (byte) 0;
// If the AndX command is disabled clear the offset to the chained packet
if ( cmd == PacketType.NoChainedCommand)
setParameter(1, 0);
}
/**
* Set the data byte count for this SMB packet
*
* @param cnt Data byte count.
*/
public final void setByteCount(int cnt) {
int offset = getByteOffset() - 2;
DataPacker.putIntelShort( cnt, m_smbbuf, offset);
}
/**
* Set the data byte count for this SMB packet
*/
public final void setByteCount() {
int offset = getByteOffset() - 2;
int len = m_pos - getByteOffset();
DataPacker.putIntelShort( len, m_smbbuf, offset);
}
/**
* Set the data byte area in the SMB packet
*
* @param byts Byte array containing the data to be copied to the SMB packet.
*/
public final void setBytes(byte[] byts) {
int offset = getByteOffset() - 2;
DataPacker.putIntelShort( byts.length, m_smbbuf, offset);
offset += 2;
for (int idx = 0; idx < byts.length; m_smbbuf[offset + idx] = byts[idx++]);
}
/**
* Set the SMB command
*
* @param cmd SMB command code
*/
public final void setCommand(int cmd) {
m_pkttype = cmd;
m_smbbuf[COMMAND] = (byte) cmd;
}
/**
* Set the SMB error class.
*
* @param cl SMB error class.
*/
public final void setErrorClass(int cl) {
m_smbbuf[ERRORCLASS] = (byte) (cl & 0xFF);
}
/**
* Set the SMB error code
*
* @param sts SMB error code.
*/
public final void setErrorCode(int sts) {
m_smbbuf[ERROR] = (byte) (sts & 0xFF);
}
/**
* Set the SMB flags value.
*
* @param flg SMB flags value.
*/
public final void setFlags(int flg) {
m_smbbuf[FLAGS] = (byte) flg;
}
/**
* Set the SMB flags2 value.
*
* @param flg SMB flags2 value.
*/
public final void setFlags2(int flg) {
DataPacker.putIntelShort( flg, m_smbbuf, FLAGS2);
}
/**
* Set the multiplex identifier.
*
* @param mid Multiplex identifier
*/
public final void setMultiplexId(int mid) {
DataPacker.putIntelShort( mid, m_smbbuf, MID);
}
/**
* Set the specified parameter word.
*
* @param idx Parameter index (zero based).
* @param val Parameter value.
*/
public final void setParameter(int idx, int val) {
int pos = WORDCNT + (2 * idx) + 1;
DataPacker.putIntelShort( val, m_smbbuf, pos);
}
/**
* Set the specified parameter words.
*
* @param idx Parameter index (zero based).
* @param val Parameter value.
*/
public final void setParameterLong(int idx, int val) {
int pos = WORDCNT + (2 * idx) + 1;
DataPacker.putIntelInt(val, m_smbbuf, pos);
}
/**
* Set the parameter count
*
* @param cnt Parameter word count.
*/
public final void setParameterCount(int cnt) {
m_smbbuf[WORDCNT] = (byte) cnt;
}
/**
* Set the process identifier value (PID).
*
* @param pid Process identifier value.
*/
public final void setProcessId(int pid) {
DataPacker.putIntelShort( pid, m_smbbuf, PID);
}
/**
* Set the packet sequence number, for connectionless commands.
*
* @param seq Sequence number.
*/
public final void setSeqNo(int seq) {
DataPacker.putIntelShort( seq, m_smbbuf, SEQNO);
}
/**
* Set the session id.
*
* @param sid Session id.
*/
public final void setSID(int sid) {
DataPacker.putIntelShort( sid, m_smbbuf, SID);
}
/**
* Set the tree identifier (TID)
*
* @param tid Tree identifier value.
*/
public final void setTreeId(int tid) {
DataPacker.putIntelShort( tid, m_smbbuf, TID);
}
/**
* Set the user identifier (UID)
*
* @param uid User identifier value.
*/
public final void setUserId(int uid) {
DataPacker.putIntelShort( uid, m_smbbuf, UID);
}
/**
* Align the byte area pointer on an int (32bit) boundary
*/
public final void alignBytePointer() {
m_pos = DataPacker.longwordAlign(m_pos);
}
/**
* Reset the byte/parameter pointer area for packing/unpacking data items from the packet
*/
public final void resetBytePointer() {
m_pos = getByteOffset();
m_endpos = m_pos + getByteCount();
}
/**
* Reset the byte/parameter pointer area for packing/unpacking data items from the packet, and align
* the buffer on an int (32bit) boundary
*/
public final void resetBytePointerAlign() {
m_pos = DataPacker.longwordAlign(getByteOffset());
m_endpos = m_pos + getByteCount();
}
/**
* Reset the byte/parameter pointer area for packing/unpacking paramaters from the packet
*/
public final void resetParameterPointer() {
m_pos = PARAMWORDS;
}
/**
* Set the unpack pointer to the specified offset, for AndX processing
*
* @param off int
* @param len int
*/
public final void setBytePointer(int off, int len) {
m_pos = off;
m_endpos = m_pos + len;
}
/**
* Skip a number of bytes in the parameter/byte area
*
* @param cnt int
*/
public final void skipBytes(int cnt) {
m_pos += cnt;
}
/**
* Return the flags value as a string
*
* @return String
*/
protected final String getFlagsAsString() {
// Get the flags value
int flags = getFlags();
if ( flags == 0)
return "<None>";
StringBuffer str = new StringBuffer();
if ((flags & FLG_SUBDIALECT) != 0)
str.append("SubDialect,");
if ((flags & FLG_CASELESS) != 0)
str.append("Caseless,");
if ((flags & FLG_CANONICAL) != 0)
str.append("Canonical,");
if ((flags & FLG_OPLOCK) != 0)
str.append("Oplock,");
if ((flags & FLG_NOTIFY) != 0)
str.append("Notify,");
if ((flags & FLG_RESPONSE) != 0)
str.append("Response,");
str.setLength(str.length() - 1);
return str.toString();
}
/**
* Return the flags2 value as a string
*
* @return String
*/
protected final String getFlags2AsString() {
// Get the flags2 value
int flags2 = getFlags2();
if ( flags2 == 0)
return "<None>";
StringBuffer str = new StringBuffer();
if (( flags2 & FLG2_LONGFILENAMES) != 0)
str.append("LongFilenames,");
if (( flags2 & FLG2_EXTENDEDATTRIB) != 0)
str.append("ExtAttributes,");
if (( flags2 & FLG2_READIFEXE) != 0)
str.append("ReadIfEXE,");
if (( flags2 & FLG2_LONGERRORCODE) != 0)
str.append("LongErrorCode,");
if (( flags2 & FLG2_UNICODE) != 0)
str.append("Unicode,");
str.setLength(str.length() - 1);
return str.toString();
}
}