org.filesys.netbios.NetBIOSPacket Maven / Gradle / Ivy
Show all versions of jfileserver Show documentation
/*
* Copyright (C) 2006-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see .
*/
package org.filesys.netbios;
import org.filesys.debug.Debug;
import org.filesys.util.DataPacker;
import org.filesys.util.HexDump;
/**
* NetBIOS Packet Class
*
*
* A NetBIOSPacket holds a single NetBIOS request or response. Contains methods for building the
* main NetBIOS request types (add name, delete name, name query, refresh and session setup).
*
* @author gkspencer
*/
public class NetBIOSPacket {
// 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 = 0x0200;
public static final int NAME_ACTIVE = 0x0400;
public static final int NAME_CONFLICT = 0x0800;
public static final int NAME_DEREG = 0x1000;
public static final int NAME_GROUP = 0x8000;
public static final int NAME_TYPE_BNODE = 0x0000;
public static final int NAME_TYPE_PNODE = 0x2000;
public static final int NAME_TYPE_MNODE = 0x4000;
public static final int NAME_TYPE_RESVD = 0x6000;
// Adapter status name in encoded format
private static final String AdapterStatusNBName = "CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
// 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
Debug.println("NetBIOS Packet Dump :-");
// Determine the packet type
if (sessPkt == true) {
switch (getPacketType()) {
// NetBIOS session request
case REQUEST:
StringBuffer name = new StringBuffer();
for (int i = 0; i < 32; i++)
name.append((char) m_nbbuf[39 + i]);
Debug.println("Session request from " + NetBIOSSession.DecodeName(name.toString()));
break;
// NetBIOS message
case MESSAGE:
break;
}
} else {
// Display the packet type
Debug.println(" Transaction Id : " + getTransactionId());
Debug.print(" Opcode : ");
switch (getOpcode()) {
case NAME_QUERY:
Debug.println("QUERY");
break;
case RESP_QUERY:
Debug.println("QUERY (Response)");
break;
case NAME_REGISTER:
Debug.println("NAME REGISTER");
break;
case RESP_REGISTER:
Debug.println("NAME REGISTER (Response)");
break;
case NAME_RELEASE:
Debug.println("NAME RELEASE");
break;
case RESP_RELEASE:
Debug.println("NAME RELEASE (Response)");
break;
case WACK:
Debug.println("WACK");
break;
case REFRESH:
Debug.println("REFRESH");
break;
default:
Debug.println(Integer.toHexString(getOpcode()));
break;
}
// Display the flags
Debug.println(" Flags : " + Integer.toHexString(getFlags()));
// Display the name counts
Debug.println(" QDCount : " + getQuestionCount());
Debug.println(" ANCount : " + getAnswerCount());
Debug.println(" NSCount : " + getNameServiceCount());
Debug.println(" ARCount : " + getAdditionalCount());
// Dump the question name, if there is one
if (getQuestionCount() > 0) {
Debug.print(" QName : ");
// 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());
Debug.println(name + " <" + NetBIOSName.TypeAsString(name.charAt(15)) + ">");
}
}
// Dump the raw data
Debug.println("********** 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);
}
// Set the MAC address of the server
setMACAddress(nameList, pos);
// 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) {
// Check that there is enough buffer space for the next name record
if ((pos + 18) > m_nbbuf.length)
throw new ArrayIndexOutOfBoundsException("NetBIOS packet length " + m_nbbuf.length);
// 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--;
}
// Set the MAC address of the server
setMACAddress(nameList, pos);
// Return the name list
return nameList;
}
/**
* Set the MAC address of the server
*
* @param nameList NetBIOSNameList
* @param pos int
*/
private void setMACAddress(NetBIOSNameList nameList, int pos) {
if ((pos + 6) > m_nbbuf.length)
return;
byte[] mac = new byte[6];
System.arraycopy(m_nbbuf, pos, mac, 0, 6);
nameList.setMACAddress(mac);
}
/**
* 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 RFCNetBIOSProtocol.MsgType
*/
public final RFCNetBIOSProtocol.MsgType getPacketType() {
return RFCNetBIOSProtocol.MsgType.fromInt((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.
*
* @return String
*/
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.
*
* @return int
*/
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 String
* @param ntyp char
* @param qtyp int
* @param qcls int
* @return 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.
*
* @param off int
* @param ipaddr byte[]
* @return int
*/
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.
*
* @param off int
* @param flg int
* @return 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 String
* @param ntyp char
* @param qtyp int
* @param qcls int
* @return 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.
*
* @param off int
* @param flg int
* @param data byte[]
* @param len int
* @return 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.
*
* @param off int
* @param len int
* @return 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 rroff Offset to name.
* @param qtyp int
* @param qcls int
* @return 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.
*
* @param off int
* @param ttl int
* @return 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;
}
/**
* 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 query request packet for the specified NetBIOS name
*
* @param name NetBIOSName
* @param tranId int
* @param wins boolean
* @return int
*/
public final int buildNameQueryRequest(NetBIOSName name, int tranId, boolean wins) {
// Initialize a name query NetBIOS packet
setTransactionId(tranId);
setOpcode(NetBIOSPacket.NAME_QUERY);
int flags = NetBIOSPacket.FLG_RECURSDES;
if (wins == false)
flags += NetBIOSPacket.FLG_BROADCAST;
setFlags(flags);
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.MsgType.REQUEST.intValue();
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;
}
/**
* Build an adapter status response
*
* @param nameList NetBIOSNameList
* @param nodeType int
* @return int
*/
public final int buildAdapterStatusResponse(NetBIOSNameList nameList, int nodeType) {
// Fill in the header
setOpcode(NetBIOSPacket.RESP_QUERY);
setFlags(NetBIOSPacket.FLG_RECURSDES + NetBIOSPacket.FLG_AUTHANSWER);
setQuestionCount(0);
setAnswerCount(1);
setAdditionalCount(0);
setNameServiceCount(0);
// Pack the encoded adapter status name into the NetBIOS packet
int pos = NB_DATA;
m_nbbuf[pos++] = (byte) NAME_LEN;
pos = DataPacker.putString(AdapterStatusNBName, m_nbbuf, pos, true);
// Set the name type and class
DataPacker.putShort((short) 0x21, m_nbbuf, pos);
pos += 2;
DataPacker.putShort((short) 0x01, m_nbbuf, pos);
pos += 2;
pos = setTTL(pos, 10000);
pos = setResourceDataLength(pos, (nameList.numberOfNames() * 18) + 42);
// Pack the names
m_nbbuf[pos++] = (byte) nameList.numberOfNames();
for (int i = 0; i < nameList.numberOfNames(); i++) {
// Get the current name
NetBIOSName nbName = nameList.getName(i);
// Pack the NetBIOS name and flags
System.arraycopy(nbName.getNetBIOSName(), 0, m_nbbuf, pos, NetBIOSName.NameLength);
pos += NetBIOSName.NameLength;
int flags = nodeType + NAME_ACTIVE;
if (nbName.isGroupName())
flags += NAME_GROUP;
DataPacker.putShort((short) flags, m_nbbuf, pos);
pos += 2;
}
// Zero out the statistics, MAC address area
for (int i = 0; i < 42; i++)
m_nbbuf[pos++] = (byte) 0;
// Set the packet length, and return the length
setLength(pos);
return getLength();
}
}