/* * Copyright 2011 Future Systems, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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.krakenapps.pcap.decoder.netbios; import org.krakenapps.pcap.util.Buffer; public class NetBiosNameHeader { public enum Opcode { Unknown(-1), Query(0), Registration(5), Release(6), Wack(7), Refresh(8); private int code; Opcode(int code) { this.code = code; } public int getCode() { return code; } public static Opcode parse(int value) { for (Opcode opcode : values()) if (opcode.getCode() == value) return opcode; return Unknown; } } // rcode public enum ResultCode { Unknown(-1), NoError(0), FormatError(1), ServerFailure(2), UnsupportedRequestError(4), RefulsedError(5), ActiveError( 6), ConflictError(7); private int value; ResultCode(int value) { this.value = value; } public int getValue() { return value; } public static ResultCode parse(int value) { for (ResultCode code : values()) if (code.getValue() == value) return code; return Unknown; } } // query or response bit public static final short ResponseMask = (short) 0x10; // 10000000 , // 00000000 // opcode field public static final short OpcodeMask = (short) 0x0f; // NM_flags field public static final short Broadcast = (short) 0x01;// 00000000 , 00010000 public static final short RecursionAvailable = (short) 0x08;// 00000000 , // 10000000 public static final short RecursionDesired = (short) 0x10;// 00000001 , // 00000000 public static final short Truncation = (short) 0x20;// 00000010 , 00000000 public static final short AuthoritativeAnswer = (short) 0x40;// 00000100 , // 00000000 // RCODE ERR public static final short FMT_ERR = (short) 0x01; public static final short SRV_ERR = (short) 0x02; public static final short IMP_ERR = (short) 0x04; public static final short RFS_ERR = (short) 0x05; public static final short ACT_ERR = (short) 0x06; public static final short CFT_ERR = (short) 0x07; /* header */ private int transactionId = 0; private boolean isResponse; // 5bit private Opcode opcode; // 7bit private int nmFlags; // 4bit private ResultCode resultCode; // questions private int qdCount = 0; // answers private int anCount = 0; // authorities private int nsCount = 0; // additionals private int arCount = 0; /* header */ private NetBiosNameHeader() { } public Opcode getOpcode() { return opcode; } public ResultCode getResultCode() { return resultCode; } public boolean isAuthoritativeAnswer() { return (nmFlags & AuthoritativeAnswer) == AuthoritativeAnswer; } public boolean isTruncation() { return (nmFlags & Truncation) == Truncation; } public boolean isRecursionDesired() { return (nmFlags & RecursionDesired) == RecursionDesired; } public boolean isRecursionAvailable() { return (nmFlags & RecursionAvailable) == RecursionAvailable; } public boolean isResponse() { return isResponse; } public int getQuestionCount() { return qdCount; } public int getAnswerCount() { return anCount; } public int getAdditionalCoount() { return arCount; } public int getAuthorityCount() { return nsCount; } public void setTransactionId(short id) { transactionId = id & 0xffff; } public void setQuestionCount(int count) { qdCount = count; } public void setAnswerCount(int count) { anCount = count; } public void setAdditionalCount(int count) { arCount = count; } public void setAuthorityCount(int count) { nsCount = count; } public int getTransactionId() { return transactionId; } public void setOpcode(short opcode) { this.opcode = Opcode.parse(opcode & 0xffff); } public static NetBiosNameHeader parse(Buffer b) { NetBiosNameHeader header = new NetBiosNameHeader(); header.setTransactionId(b.getShort()); header.parseOpCode(b.getShort()); header.setQuestionCount(b.getShort()); header.setAnswerCount(b.getShort()); header.setAuthorityCount(b.getShort()); header.setAdditionalCount(b.getShort()); return header; } // this function is called in only netbiosNamePacket class public static NetBiosNameHeader makeNameHeader() { return new NetBiosNameHeader(); } // private void parseOpCode(short value) { int op = (value >> 11) & 0xff; isResponse = (op & ResponseMask) == ResponseMask; this.opcode = Opcode.parse(op); this.nmFlags = (value >> 4) & 0x7f; this.resultCode = ResultCode.parse((value) & 0x0f); /* * if( (!isResponse) && (this.resultCode != ResultCode.NoError)) { throw * new * IllegalArgumentException("Query packet is can't contained error Code = " * + this.resultCode); } */ } public short decodeOpCode() { short value; value = ((short) (this.opcode.getCode() << 11)); value = (short) (value | (short) (this.nmFlags << 4)); value = (short) (value | (short) (this.resultCode.getValue())); return value; } @Override public String toString() { return String.format("NetBiosNameHeader \n" + "tx=0x%x, response=%s, opcode=%s, " + "nmflag=0x%x, result=%s, qd=%d, an=%d, ns=%d, ar=%d\n", this.transactionId, this.isResponse, this.opcode, this.nmFlags, this.resultCode, this.qdCount, this.anCount, this.nsCount, this.arCount); } }