added decode support for 'poll inactive station' ipx message
[obnox/wireshark/wip.git] / packet-netbios.c
index afab7175254de28a3b36596ff054a68fcdc8e341..3b2b21bf100647faeb5200a2e3a5a71ebc176079 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * derived from the packet-nbns.c
  *
- * $Id: packet-netbios.c,v 1.1 1999/08/10 20:05:41 guy Exp $
+ * $Id: packet-netbios.c,v 1.11 1999/11/30 07:45:41 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 #include <string.h>
 #include <glib.h>
 #include "packet.h"
-#include "packet-dns.h"
+#include "packet-netbios.h"
 #include "util.h"
 
 /* Netbios command numbers */
 #define NB_ADD_GROUP           0x00
 #define NB_ADD_NAME            0x01
+#define NB_NAME_IN_CONFLICT    0x02
+#define NB_STATUS_QUERY                0x03
+#define NB_TERMINATE_TRACE_R   0x07
 #define NB_DATAGRAM            0x08
+#define NB_DATAGRAM_BCAST      0x09
 #define NB_NAME_QUERY          0x0a
+#define NB_ADD_NAME_RESP       0x0d
 #define NB_NAME_RESP           0x0e
+#define NB_STATUS_RESP                 0x0f
+#define NB_TERMINATE_TRACE_LR  0x13
 #define NB_DATA_ACK            0x14
+#define NB_DATA_FIRST_MIDDLE   0x15
 #define NB_DATA_ONLY_LAST      0x16
-#define NB_SESSION_CONFIRM     0x17    
-#define NB_SESSION_INIT                0x19    
+#define NB_SESSION_CONFIRM     0x17
+#define NB_SESSION_END         0x18
+#define NB_SESSION_INIT                0x19
+#define NB_NO_RECEIVE          0x1a
+#define NB_RECEIVE_OUTSTANDING 0x1b
+#define NB_RECEIVE_CONTINUE    0x1c
 #define NB_KEEP_ALIVE          0x1f
 
-
 /* Offsets of fields in the NetBIOS header. */
 #define NB_LENGTH              0
 #define        NB_DELIMITER            2
 #define        NB_RECVER_NAME          12
 #define        NB_SENDER_NAME          28
 
+static int proto_netbios = -1;
 
+static gint ett_netb = -1;
+static gint ett_netb_name = -1;
+static gint ett_netb_flags = -1;
+static gint ett_netb_status = -1;
 
+/* The strings for the station type, used by get_netbios_name function;
+   many of them came from the file "NetBIOS.txt" in the Zip archive at
 
-static int proto_netbios = -1;
+       http://www.net3group.com/ftp/browser.zip
+ */
 
-/* a number to bit image table */
-
-static char *bit_field_str[] = {
-       "000",
-       "001",
-       "010",
-       "011",
-       "100",
-       "101",
-       "110",
-       "111"};
-       
+static const value_string name_type_vals[] = {
+       {0x00,  "Workstation/Redirector"},
+       {0x01,  "Browser"},
+       {0x02,  "Workstation/Redirector"}, 
+               /* not sure what 0x02 is, I'm seeing alot of them however */
+               /* i'm seeing them with workstation/redirection host 
+                       announcements */
+       {0x03,  "Messenger service/Main name"},
+       {0x05,  "Forwarded name"},
+       {0x06,  "RAS Server service"},
+       {0x1b,  "PDC Domain name"},
+       {0x1c,  "BDC Domain name"},
+       {0x1d,  "Master Browser backup"},
+       {0x1e,  "Browser Election Service"},
+       {0x1f,  "Net DDE Service"},
+       {0x20,  "Server service"},
+       {0x21,  "RAS client service"},
+       {0x22,  "Exchange Interchange (MSMail Connector)"},
+       {0x23,  "Exchange Store"},
+       {0x24,  "Exchange Directory"},
+       {0x2b,  "Lotus Notes Server service"},
+       {0x30,  "Modem sharing server service"},
+       {0x31,  "Modem sharing client service"},
+       {0x43,  "SMS Clients Remote Control"},
+       {0x44,  "SMS Administrators Remote Control Tool"},
+       {0x45,  "SMS Clients Remote Chat"},
+       {0x46,  "SMS Clients Remote Transfer"},
+       {0x4c,  "DEC Pathworks TCP/IP Service on Windows NT"},
+       {0x52,  "DEC Pathworks TCP/IP Service on Windows NT"},
+       {0x6a,  "Microsoft Exchange IMC"},
+       {0x87,  "Microsoft Exchange MTA"},
+       {0xbe,  "Network Monitor Agent"},
+       {0xbf,  "Network Monitor Analyzer"},
+       {0x00,  NULL}
+};
 
-/* the strings for the station type, used by get_netbios_name function */
+/* See
+   
+       http://www.s390.ibm.com/bookmgr-cgi/bookmgr.cmd/BOOKS/BK8P7001/CCONTENTS
 
-char *name_type_str[] = {
-       "Workstation/Redirector",       /* 0x00 */
-       "Browser",                      /* 0x01 */
-       "Unknown",
-       "Messenger service/Main name",  /* 0x03 */
-       "Unknown",
-       "Forwarded name",               /* 0x05 */
-       "RAS Server service",           /* 0x06 */
-       "Unknown",
-       "Unknown",
-       "Unknown",
-       "Unknown",
-       "Unknown",
-       "Unknown",
-       "Unknown",
-       "Unknown",
-       "Unknown",
-       "Unknown",                      /* 0x10 */
+   and
+
+       http://ourworld.compuserve.com/homepages/TimothyDEvans/contents.htm
+
+   for information about the NetBIOS Frame Protocol (which is what this
+   module dissects). */
+
+/* the strings for the command types  */
+
+static char *CommandName[] = {
+       "Add Group Name Query", /* 0x00 */
+       "Add Name Query",       /* 0x01 */
+       "Name In Conflict",     /* 0x02 */
+       "Status Query",         /* 0x03 */
        "Unknown",
        "Unknown",
        "Unknown",
+       "Terminate Trace",      /* 0x07 */
+       "Datagram",             /* 0x08 */
+       "Broadcast Datagram",   /* 0x09 */
+       "Name Query",           /* 0x0A */
        "Unknown",
        "Unknown",
+       "Add Name Response",    /* 0x0D */
+       "Name Recognized",      /* 0x0E */
+       "Status Response",      /* 0x0F */
        "Unknown",
        "Unknown",
        "Unknown",
+       "Terminate Trace",      /* 0x13 */
+       "Data Ack",             /* 0x14 */
+       "Data First Middle",    /* 0x15 */
+       "Data Only Last",       /* 0x16 */
+       "Session Confirm",      /* 0x17 */
+       "Session End",          /* 0x18 */
+       "Session Initialize",   /* 0x19 */
+       "No Receive",           /* 0x1a */
+       "Receive Outstanding",  /* 0x1b */
+       "Receive Continue",     /* 0x1c */
        "Unknown",
        "Unknown",
-       "PDC Domain name",              /* 0x1b */
-       "BDC Domain name",              /* 0x1c */
-       "Master Browser backup",        /* 0x1d */
-       "Browser Election Service",     /* 0x1e */
-       "Net DDE Service",              /* 0x1f */
-       "Server service",               /* 0x20 */
-       "RAS client service",           /* 0x21 */
-       "Unknown",      /* need 'Unknown' as last entry (for limiting stuff) */
+       "Session Alive",        /* 0x1f */
 };
 
-static int nb_name_type_max = sizeof(name_type_str) /sizeof( char*);
-
-/* the strings for the command types  */
-
-char *CommandName[] = {
-               "Add Group Query",      /* 0x00 */
-               "Add Name Query",       /* 0x01 */
-               "Unknown",
-               "Unknown",
-               "Unknown",
-               "Unknown",
-               "Unknown",
-               "Unknown",
-               "Datagram",             /* 0x08 */
-               "Unknown",
-               "Name Query",           /* 0x0A */
-               "Unknown",
-               "Unknown",
-               "Unknown",
-               "Name Recognized",      /* 0x0E */
-               "Unknown",
-               "Unknown",
-               "Unknown",
-               "Unknown",
-               "Unknown",
-               "Data Ack",             /* 0x14 */
-               "Unknown",
-               "Data Only Last",       /* 0x16 */
-               "Session Confirm",      /* 0x17 */
-               "Unknown",
-               "Session Initialize",   /* 0x19 */
-               "Unknown",
-               "Unknown",
-               "Unknown",
-               "Unknown",
-               "Unknown",
-               "Session Alive",        /* 0x1f */
-       };
-
 void capture_netbios(const u_char *pd, int offset, guint32 cap_len,
        packet_counts *ld)
 {
@@ -175,131 +186,206 @@ void capture_netbios(const u_char *pd, int offset, guint32 cap_len,
 }
 
 
-static uint get_netbios_name(const u_char *data_ptr, int offset, char *name_ret)
+int
+process_netbios_name(const u_char *name_ptr, char *name_ret)
+{
+       int i;
+       int name_type = *(name_ptr + NETBIOS_NAME_LEN - 1);
+       u_char name_char;
+       static const char hex_digits[16] = "0123456780abcdef";
+
+       for (i = 0; i < NETBIOS_NAME_LEN - 1; i++) {
+               name_char = *name_ptr++;
+               if (name_char >= ' ' && name_char <= '~')
+                       *name_ret++ = name_char;
+               else {
+                       /* It's not printable; show it as <XX>, where
+                          XX is the value in hex. */
+                       *name_ret++ = '<';
+                       *name_ret++ = hex_digits[(name_char >> 4)];
+                       *name_ret++ = hex_digits[(name_char & 0x0F)];
+                       *name_ret++ = '>';
+               }
+       }
+       *name_ret = '\0';
+       return name_type;
+}
+
+int get_netbios_name(const u_char *pd, int offset, char *name_ret)
 
 {/*  Extract the name string and name type.  Return the name string in  */
  /* name_ret and return the name_type. */
-
-       int i;
-       char  name_type = *(data_ptr + offset + 15);
-       const char *name_ptr = data_ptr + offset;
-
-       for( i = 0; i <16; ++i){
-               if ( 0x20 == (*name_ret++ = *name_ptr++))       /* exit if space */
-                       break;
+       if (!BYTES_ARE_IN_FRAME(offset, NETBIOS_NAME_LEN)) {
+               /*
+                * Name goes past end of captured data in packet.
+                */
+               return -1;
        }
-
-       *name_ret = 0;
-       return (uint)name_type;
+       return process_netbios_name(&pd[offset], name_ret);
 }
 
+/*
+ * Get a string describing the type of a NetBIOS name.
+ */
+char *
+netbios_name_type_descr(int name_type)
+{
+       return val_to_str(name_type, name_type_vals, "Unknown");
+}
 
-static void netbios_add_name( char* label, const u_char *pd, int offset,
-    int nb_offset, proto_tree *tree)
+gboolean netbios_add_name(char* label, const u_char *pd, int offset,
+    proto_tree *tree)
 
 {/* add a name field display tree. Display the name and station type in sub-tree */
- /* NOTE: offset = offset to start of netbios header   */
- /*      nb_offset = offset inside of netbios header   */
  
        proto_tree *field_tree;
        proto_item *tf;
-       char  name_str[ 17];
+       char  name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
        int   name_type;
+       char  *name_type_str;
 
                                        /* decode the name field */
-       name_type = get_netbios_name( pd, nb_offset, name_str);
+       name_type = get_netbios_name(pd, offset, name_str);
+       if (name_type < 0) {
+               /*
+                * Name goes past end of captured data in packet.
+                */
+               return FALSE;
+       }
 
-       if ( nb_name_type_max < name_type)      /* limit type value */
-               name_type = nb_name_type_max;
-       
-       tf = proto_tree_add_text( tree, offset + nb_offset, 16,
-               "%s: %s (%s)", label, name_str, name_type_str[name_type]);
+       name_type_str = netbios_name_type_descr(name_type);
+       tf = proto_tree_add_text( tree, offset, NETBIOS_NAME_LEN,
+               "%s: %s<%02x> (%s)", label, name_str, name_type, name_type_str);
 
-       field_tree = proto_item_add_subtree( tf, ETT_NETB_NAME);
+       field_tree = proto_item_add_subtree( tf, ett_netb_name);
        
-       proto_tree_add_text( field_tree, offset + nb_offset, 15, "%s",
+       proto_tree_add_text( field_tree, offset, 15, "%s",
            name_str);
-       proto_tree_add_text( field_tree, offset + nb_offset + 15, 1,
-           "0x%0x (%s)", name_type, name_type_str[ name_type]);
+       proto_tree_add_text( field_tree, offset + 15, 1,
+           "0x%02x (%s)", name_type, name_type_str);
+       return TRUE;
 }
 
 
-static void netbios_add_flags( const u_char *pd, proto_tree *tree, int offset)
+static void netbios_data_first_middle_flags(const u_char *pd, proto_tree *tree,
+    int offset)
 
 {
-
        proto_tree *field_tree;
        proto_item *tf;
-       uint flags = *(pd + offset);
-                                       /* decode the flag field */
+       guint flags = pd[offset];
+               /* decode the flag field for Data First Middle packet*/
+
+       tf = proto_tree_add_text(tree, offset, 1,
+                       "Flags: 0x%02x", flags);
+       field_tree = proto_item_add_subtree(tf, ett_netb_flags);
 
+       proto_tree_add_text(field_tree, offset, 1, "%s",
+           decode_boolean_bitfield(flags, 0x08, 8,
+               "Acknowledge_included", "No Acknowledge_included"));
+
+       proto_tree_add_text(field_tree, offset, 1, "%s",
+           decode_boolean_bitfield(flags, 0x02, 8,
+               "No acknowledgement expected", "Acknowledgement expected"));
 
-       tf = proto_tree_add_text( tree, offset, 1,
+       proto_tree_add_text(field_tree, offset, 1, "%s",
+           decode_boolean_bitfield(flags, 0x01, 8,
+               "RECEIVE_CONTINUE requested", "RECEIVE_CONTINUE not requested"));
+}
+
+
+static void netbios_data_only_flags(const u_char *pd, proto_tree *tree,
+    int offset)
+{
+       proto_tree *field_tree;
+       proto_item *tf;
+       guint flags = pd[offset];
+               /* decode the flag field for Data Only Last packet*/
+
+       tf = proto_tree_add_text(tree, offset, 1,
                        "Flags: 0x%02x", flags);
-       field_tree = proto_item_add_subtree(tf, ETT_NETB_FLAGS);
+       field_tree = proto_item_add_subtree(tf, ett_netb_flags);
 
-       proto_tree_add_text( field_tree, offset, 1, "%s%s",
-               decode_boolean_bitfield(flags, 0x80,
-                       8, "No", ""), " NO.ACK indicator");
+       proto_tree_add_text(field_tree, offset, 1, "%s",
+           decode_boolean_bitfield(flags, 0x08, 8,
+               "ACKNOWLEDGE_INCLUDED", "No ACKNOWLEDGE_INCLUDED"));
 
-       proto_tree_add_text(field_tree, offset, 1,
-                ".... %s. = Largest Frame Size = %d", 
-               bit_field_str[(flags & 0x0e) >> 1], ((flags & 0x0e) >> 1));
+       proto_tree_add_text(field_tree, offset, 1, "%s",
+           decode_boolean_bitfield(flags, 0x04, 8,
+               "ACKNOWLEDGE_WITH_DATA_ALLOWED", "No ACKNOWLEDGE_WITH_DATA_ALLOWED"));
 
        proto_tree_add_text(field_tree, offset, 1, "%s",
-               decode_boolean_bitfield( flags, 0x01,
-                       8, "Version 2.0 or higher", "Pre version 2.0"));
+           decode_boolean_bitfield(flags, 0x02, 8,
+               "No acknowledgement expected", "Acknowledgement expected"));
 }
 
 
-static void netbios_add_ses_confirm_flags( const u_char *pd, proto_tree *tree,
+static void netbios_add_ses_confirm_flags(const u_char *pd, proto_tree *tree,
        int offset)
-
 {
        proto_tree *field_tree;
        proto_item *tf;
-       uint flags = *(pd + offset);
-                                       /* decode the flag field */
+       guint flags = pd[offset];
+               /* decode the flag field for Session Confirm packet */
 
+       tf = proto_tree_add_text(tree, offset, 1,
+                       "Flags: 0x%02x", flags);
+       field_tree = proto_item_add_subtree( tf, ett_netb_flags);
 
-       tf = proto_tree_add_text( tree, offset, 1,
+       proto_tree_add_text(field_tree, offset, 1, "%s",
+           decode_boolean_bitfield(flags, 0x80, 8,
+               "Can handle SEND.NO.ACK", "Can't handle SEND.NO.ACK"));
+
+       proto_tree_add_text(field_tree, offset, 1, "%s",
+           decode_boolean_bitfield(flags, 0x01, 8,
+               "NetBIOS 2.00 or higher", "NetBIOS 1.xx"));
+}
+
+
+static void netbios_add_session_init_flags(const u_char *pd, proto_tree *tree,
+       int offset)
+{
+       proto_tree *field_tree;
+       proto_item *tf;
+       guint flags = pd[offset];
+               /* decode the flag field for Session Init packet */
+
+       tf = proto_tree_add_text(tree, offset, 1,
                        "Flags: 0x%02x", flags);
-       field_tree = proto_item_add_subtree( tf, ETT_NETB_FLAGS);
+       field_tree = proto_item_add_subtree(tf, ett_netb_flags);
+
+       proto_tree_add_text(field_tree, offset, 1, "%s",
+           decode_boolean_bitfield(flags, 0x80, 8,
+               "Can handle SEND.NO.ACK", "Can't handle SEND.NO.ACK"));
 
-       proto_tree_add_text(field_tree, offset, 1, "%s%s",
-                       decode_boolean_bitfield(flags, 0x80,
-                               8, "No", ""), " NO.ACK indicator");
+       proto_tree_add_text(field_tree, offset, 1, "%s",
+           decode_numeric_bitfield(flags, 0x0E, 8,
+               "Largest frame value = %u"));
 
        proto_tree_add_text(field_tree, offset, 1, "%s",
-                       decode_boolean_bitfield(flags, 0x01,
-                               8, "Pre version 2.0", "Version 2.0 or higher"));
+           decode_boolean_bitfield(flags, 0x01, 8,
+               "NetBIOS 2.00 or higher", "NetBIOS 1.xx"));
 }
 
 
-static void netbios_data_only_flags( const u_char *pd, proto_tree *tree,
+static void netbios_no_receive_flags(const u_char *pd, proto_tree *tree,
     int offset)
 
 {
        proto_tree *field_tree;
        proto_item *tf;
-       uint flags = *(pd + offset);
-                                       /* decode the flag field for data_only packet*/
+       guint flags = pd[offset];
+               /* decode the flag field for No Receive packet*/
 
-
-       tf = proto_tree_add_text( tree, offset, 1,
+       tf = proto_tree_add_text(tree, offset, 1,
                        "Flags: 0x%02x", flags);
-       field_tree = proto_item_add_subtree(tf, ETT_NETB_FLAGS);
-
-       proto_tree_add_text(field_tree, offset, 1, "%s%s",
-                       decode_boolean_bitfield(flags, 0x08,
-                               8, "", "No "), "Acknowledge_Included");
-       proto_tree_add_text(field_tree, offset, 1, "%s%s",
-                       decode_boolean_bitfield(flags, 0x04,
-                               8, "", "No "), "Ack_with_data_allowed");
 
-       proto_tree_add_text(field_tree, offset, 1, "%s%s",
-                       decode_boolean_bitfield(flags, 0x02,
-                               8, "", "No "), "NO.ACK indicator");
+       if (flags & 0x02) {
+               field_tree = proto_item_add_subtree(tf, ett_netb_flags);
+               proto_tree_add_text(field_tree, offset, 1, "%s",
+                   decode_boolean_bitfield(flags, 0x02, 8,
+                       "SEND.NO.ACK data not received", NULL));
+       }
 }
 
 
@@ -310,78 +396,105 @@ static void netbios_data_only_flags( const u_char *pd, proto_tree *tree,
 /************************************************************************/
 
 
-static void nb_xmit_corrl(const u_char *data_ptr, int offset, proto_tree *tree)
+static void nb_xmit_corrl(const u_char *pd, int offset, proto_tree *tree)
 
 {/* display the transmit correlator */
 
        proto_tree_add_text( tree, offset + NB_XMIT_CORL, 2,
-           "Transmit Correlator: 0x%04x", pletohs( data_ptr + NB_XMIT_CORL));
+           "Transmit Correlator: 0x%04x", pletohs(&pd[offset + NB_XMIT_CORL]));
 }
 
 
-static void nb_resp_corrl(const u_char *data_ptr, int offset, proto_tree *tree)
+static void nb_resp_corrl(const u_char *pd, int offset, proto_tree *tree)
 
 {/* display the response correlator */
 
        proto_tree_add_text( tree, offset + NB_RESP_CORL, 2,
-           "Response Correlator: 0x%04x", pletohs( data_ptr + NB_RESP_CORL));
+           "Response Correlator: 0x%04x", pletohs(&pd[offset + NB_RESP_CORL]));
 }
 
 
-static void nb_call_name_type(const u_char *data_ptr, int offset,
+static void nb_call_name_type(const u_char *pd, int offset,
     proto_tree *tree)
 
 {/* display the call name type */
 
-       int name_type_value = MIN(*(data_ptr + NB_CALL_NAME_TYPE),
-               nb_name_type_max);
+       int name_type_value = pd[offset + NB_CALL_NAME_TYPE];
        
-       proto_tree_add_text( tree, offset + NB_CALL_NAME_TYPE, 1,
-           "Caller's Name Type.: 0x%02x (%s)",
-           *(data_ptr + NB_CALL_NAME_TYPE),
-           name_type_str[ name_type_value]);
+       switch (name_type_value) {
+
+       case 0x00:
+               proto_tree_add_text( tree, offset + NB_CALL_NAME_TYPE, 1,
+                   "Caller's Name Type: Unique name");
+               break;
+
+       case 0x01:
+               proto_tree_add_text( tree, offset + NB_CALL_NAME_TYPE, 1,
+                   "Caller's Name Type: Group name");
+               break;
+
+       default:
+               proto_tree_add_text( tree, offset + NB_CALL_NAME_TYPE, 1,
+                   "Caller's Name Type: 0x%02x (should be 0 or 1)",
+                   name_type_value);
+               break;
+       }
 }
 
 
-static void nb_local_session(const u_char *data_ptr, int offset,
+static void nb_local_session(const u_char *pd, int offset,
     proto_tree *tree)
 
 {/* add the local session to tree */
                        
-       proto_tree_add_text( tree, offset +NB_LOCAL_SES, 1,
-           "Local Session No.: 0x%02d", *(data_ptr + NB_LOCAL_SES));
+       proto_tree_add_text(tree, offset + NB_LOCAL_SES, 1,
+           "Local Session No.: 0x%02x", pd[offset + NB_LOCAL_SES]);
 }
 
 
-static void nb_remote_session(const u_char *data_ptr, int offset,
+static void nb_remote_session(const u_char *pd, int offset,
     proto_tree *tree)
 
 {/* add the remote session to tree */
                        
-       proto_tree_add_text( tree, offset +NB_RMT_SES, 1,
-           "Remote Session No.: 0x%02d", *(data_ptr + NB_RMT_SES));
+       proto_tree_add_text(tree, offset + NB_RMT_SES, 1,
+           "Remote Session No.: 0x%02x", pd[offset + NB_RMT_SES]);
 }
 
 
-static void nb_data1( char *label, const u_char *data_ptr, int offset,
+static void nb_data2(char *label, int len, const u_char *pd, int offset,
     proto_tree *tree)
 
-{/* add the DATA1 to tree with format string = label */
+{/* add the DATA2 to tree with format string = label and length of len */
 
-       proto_tree_add_text( tree, offset + NB_DATA1, 1, label,
-           *(data_ptr + NB_DATA1));
+       int value = (len == 1 ? pd[offset + NB_DATA2]
+                       : pletohs(&pd[offset + NB_DATA2]));
+       
+       proto_tree_add_text(tree, offset + NB_DATA2, len, label, value);
 }
 
-
-static void nb_data2( char *label, int len, const u_char *data_ptr, int offset,
+static void nb_resync_indicator(const u_char *pd, int offset,
     proto_tree *tree)
+{
+       guint16 resync_indicator = pletohs(&pd[offset + NB_DATA2]);
 
-{/* add the DATA2 to tree with format string = label and length of len */
+       switch (resync_indicator) {
 
-       int value = (len == 1 ? *(data_ptr + NB_DATA2)
-                       : pletohs( data_ptr + NB_DATA2));
-       
-       proto_tree_add_text( tree, offset +NB_DATA2, len, label, value);
+       case 0x0000:
+               proto_tree_add_text(tree, offset + NB_DATA2, 2,
+                   "Re-sync indicator: Not first Data First Middle following Receive Outstanding");
+               break;
+
+       case 0x0001:
+               proto_tree_add_text(tree, offset + NB_DATA2, 2,
+                   "Re-sync indicator: First Data First Middle following Receive Outstanding");
+               break;
+
+       default:
+               proto_tree_add_text(tree, offset + NB_DATA2, 2,
+                   "Re-sync indicator: 0x%04x", resync_indicator);
+               break;
+       }
 }
 
 /************************************************************************/
@@ -395,136 +508,410 @@ static void  dissect_netb_unknown(const u_char *data_ptr, int offset,
 
 {/* Handle any unknow commands, do nothing */
 
-//$$   dissect_data( data_ptr, offset + NB_COMMAND + 1, fd, tree);
+/*     dissect_data( data_ptr, offset + NB_COMMAND + 1, fd, tree); */
 }
 
 
-static void  dissect_netb_add_group(const u_char *data_ptr, int offset,
+static void  dissect_netb_add_group_name(const u_char *pd, int offset,
     frame_data *fd, proto_tree *tree)
 
-{/* Handle the ADD GROUP command */
+{/* Handle the ADD GROUP NAME QUERY command */
 
-       nb_resp_corrl( data_ptr, offset, tree); 
+       nb_resp_corrl(pd, offset, tree); 
 
-       netbios_add_name( "Group to add", data_ptr, 
-                           offset, NB_SENDER_NAME, tree);
+       netbios_add_name("Group name to add", pd, offset + NB_SENDER_NAME,
+           tree);
 }
 
 
-static void  dissect_netb_add_name(const u_char *data_ptr, int offset, 
+static void  dissect_netb_add_name(const u_char *pd, int offset, 
     frame_data *fd, proto_tree *tree)
 
-{/* Handle the ADD NAME command */
+{/* Handle the ADD NAME QUERY command */
 
-       nb_resp_corrl( data_ptr, offset, tree); 
+       nb_resp_corrl(pd, offset, tree); 
 
-       netbios_add_name( "Name to add", data_ptr, 
-                           offset, NB_SENDER_NAME, tree);
+       netbios_add_name("Name to add", pd, offset + NB_SENDER_NAME, tree);
 }
 
 
-static void  dissect_netb_name_query(const u_char *data_ptr, int offset,
+static void  dissect_netb_name_in_conflict(const u_char *pd, int offset,
     frame_data *fd, proto_tree *tree)
 
-{/* Handle the NAME QUERY command */
+{/* Handle the NAME IN CONFLICT command */
+
+       if (!netbios_add_name("Name In Conflict", pd, offset + NB_RECVER_NAME,
+           tree))
+               return;
+       netbios_add_name("Sender's Name", pd, offset + NB_SENDER_NAME,
+           tree);
+}
+
+
+static void  dissect_netb_status_query(const u_char *pd, int offset,
+    frame_data *fd, proto_tree *tree)
+
+{/* Handle the STATUS QUERY command */
+       guint8 status_request = pd[offset + NB_DATA1];
+
+       switch (status_request) {
 
-       nb_data2( "Local Session No.: 0x%02x", 1, data_ptr, offset, tree); 
-       nb_call_name_type( data_ptr, offset, tree); 
-       netbios_add_name( "Query Name", data_ptr, offset, NB_RECVER_NAME, tree);
-       netbios_add_name( "Sender's Name", data_ptr, offset, NB_SENDER_NAME,
+       case 0:
+               proto_tree_add_text(tree, offset + NB_DATA1, 1,
+                   "Status request: NetBIOS 1.x or 2.0");
+               break;
+
+       case 1:
+               proto_tree_add_text(tree, offset + NB_DATA1, 1,
+                   "Status request: NetBIOS 2.1, initial status request");
+               break;
+
+       default:
+               proto_tree_add_text(tree, offset + NB_DATA1, 1,
+                   "Status request: NetBIOS 2.1, %u names received so far",
+                   status_request);
+               break;
+       }
+       nb_data2("Length of status buffer: %u", 2, pd, offset, tree);
+       nb_resp_corrl(pd, offset, tree); 
+       if (!netbios_add_name("Receiver's Name", pd, offset + NB_RECVER_NAME,
+           tree))
+               return;
+       netbios_add_name("Sender's Name", pd, offset + NB_SENDER_NAME,
            tree);
 }
 
 
-static void  dissect_netb_name_resp(const u_char *data_ptr, int offset,
+static u_char zeroes[10];
+
+static void  dissect_netb_datagram(const u_char *pd, int offset,
+    frame_data *fd, proto_tree *tree)
+
+{/* Handle the DATAGRAM command */
+
+       if (!netbios_add_name("Receiver's Name", pd, offset + NB_RECVER_NAME,
+           tree))
+               return;
+       /* Weird.  In some datagrams, this is 10 octets of 0, followed
+          by a MAC address.... */
+       if (memcmp(&pd[offset + NB_SENDER_NAME], zeroes, 10) == 0) {
+               proto_tree_add_text( tree, offset + NB_SENDER_NAME + 10, 6,
+                   "Sender's MAC Address: %s",
+                   ether_to_str(&pd[offset + NB_SENDER_NAME + 10]));
+       } else {
+               netbios_add_name("Sender's Name", pd, offset + NB_SENDER_NAME,
+                   tree);
+       }
+}
+
+
+static void  dissect_netb_datagram_bcast(const u_char *pd, int offset,
+    frame_data *fd, proto_tree *tree)
+
+{/* Handle the DATAGRAM BROADCAST command */
+
+       /* We assume the same weirdness can happen here.... */
+       if (memcmp(&pd[offset + NB_SENDER_NAME], zeroes, 10) == 0) {
+               proto_tree_add_text( tree, offset + NB_SENDER_NAME + 10, 6,
+                   "Sender's Node Address: %s",
+                   ether_to_str(&pd[offset + NB_SENDER_NAME + 10]));
+       } else {
+               netbios_add_name("Sender's Name", pd, offset + NB_SENDER_NAME,
+                   tree);
+       }
+}
+
+
+static void  dissect_netb_name_query(const u_char *pd, int offset,
     frame_data *fd, proto_tree *tree)
 
-{/* Handle the NAME RESPONSE command */
+{/* Handle the NAME QUERY command */
+       guint8 local_session_number = pd[offset + NB_DATA2];
+
+       if (local_session_number == 0) {
+               proto_tree_add_text( tree, offset + NB_DATA2, 1,
+                   "Local Session No.: 0 (FIND.NAME request)");
+       } else {
+               proto_tree_add_text( tree, offset + NB_DATA2, 1,
+                   "Local Session No.: 0x%02x", local_session_number);
+       }
+       nb_call_name_type(pd, offset, tree);
+       nb_resp_corrl(pd, offset, tree);
+       if (!netbios_add_name("Query Name", pd, offset + NB_RECVER_NAME, tree))
+               return;
+       if (local_session_number != 0) {
+               netbios_add_name("Sender's Name", pd, offset + NB_SENDER_NAME,
+                   tree);
+       }
+}
+
+
+static void  dissect_netb_add_name_resp(const u_char *pd, int offset,
+    frame_data *fd, proto_tree *tree)
 
-       nb_data2( "Local Session No.: 0x%02x", 1, data_ptr, offset, tree); 
+{/* Handle the ADD NAME RESPONSE command */
+       guint8 status = pd[offset + NB_DATA1];
+       guint16 name_type = pletohs(&pd[offset + NB_DATA2]);
 
-       nb_call_name_type( data_ptr, offset, tree); 
-       nb_xmit_corrl( data_ptr, offset, tree); 
-       nb_resp_corrl( data_ptr, offset, tree);
-       netbios_add_name( "Receiver's Name", data_ptr, offset, NB_RECVER_NAME,
+       switch (status) {
+
+       case 0:
+               proto_tree_add_text( tree, offset + NB_DATA1, 1,
+                   "Status: Add name not in process");
+               break;
+
+       case 1:
+               proto_tree_add_text( tree, offset + NB_DATA1, 1,
+                   "Status: Add name in process");
+               break;
+
+       default:
+               proto_tree_add_text( tree, offset + NB_DATA1, 1,
+                   "Status: 0x%02x (should be 0 or 1)", status);
+               break;
+       }
+
+       switch (name_type) {
+
+       case 0:
+               proto_tree_add_text( tree, offset + NB_DATA2, 2,
+                   "Name type: Unique name");
+               break;
+
+       case 1:
+               proto_tree_add_text( tree, offset + NB_DATA2, 2,
+                   "Name type: Group name");
+               break;
+
+       default:
+               proto_tree_add_text( tree, offset + NB_DATA2, 2,
+                   "Name type: 0x%04x (should be 0 or 1)", name_type);
+               break;
+       }
+
+       nb_xmit_corrl(pd, offset, tree); 
+       if (!netbios_add_name("Name to be added", pd, offset + NB_RECVER_NAME,
+           tree))
+               return;
+       netbios_add_name("Name to be added", pd, offset + NB_SENDER_NAME,
            tree);
-       netbios_add_name( "Sender's Name", data_ptr, offset, NB_SENDER_NAME,
+}
+
+
+static void  dissect_netb_name_resp(const u_char *pd, int offset,
+    frame_data *fd, proto_tree *tree)
+
+{/* Handle the NAME RECOGNIZED command */
+       guint8 local_session_number = pd[offset + NB_DATA2];
+
+       switch (local_session_number) {
+
+       case 0x00:
+               proto_tree_add_text( tree, offset + NB_DATA2, 1,
+                   "State of name: No LISTEN pending, or FIND.NAME response");
+               break;
+
+       case 0xFF:
+               proto_tree_add_text( tree, offset + NB_DATA2, 1,
+                   "State of name: LISTEN pending, but insufficient resources to establish session");
+               break;
+
+       default:
+               proto_tree_add_text( tree, offset + NB_DATA2, 1,
+                   "Local Session No.: 0x%02x", local_session_number);
+               break;
+       }
+       nb_call_name_type(pd, offset, tree);
+       nb_xmit_corrl(pd, offset, tree);
+       if (local_session_number != 0x00 && local_session_number != 0xFF)
+               nb_resp_corrl(pd, offset, tree);
+       if (!netbios_add_name("Receiver's Name", pd, offset + NB_RECVER_NAME,
+           tree))
+               return;
+       if (local_session_number != 0x00 && local_session_number != 0xFF) {
+               netbios_add_name("Sender's Name", pd, offset + NB_SENDER_NAME,
+                   tree);
+       }
+}
+
+
+static void  dissect_netb_status_resp(const u_char *pd, int offset,
+    frame_data *fd, proto_tree *tree)
+
+{/* Handle the STATUS RESPONSE command */
+       guint8 status_response = pd[offset + NB_DATA1];
+       proto_item *td2;
+       proto_tree *data2_tree;
+       guint16 data2;
+
+       nb_call_name_type(pd, offset, tree);
+       if (status_response == 0) {
+               proto_tree_add_text(tree, offset + NB_DATA1, 1,
+                   "Status response: NetBIOS 1.x or 2.0");
+       } else {
+               proto_tree_add_text(tree, offset + NB_DATA1, 1,
+                   "Status response: NetBIOS 2.1, %u names sent so far",
+                   status_response);
+       }
+       data2 = pletohs(&pd[offset + NB_DATA2]);
+       td2 = proto_tree_add_text(tree, offset + NB_DATA2, 2, "Status: 0x04x",
+           data2);
+       data2_tree = proto_item_add_subtree(td2, ett_netb_status);
+       if (data2 & 0x8000) {
+               proto_tree_add_text(data2_tree, offset, 2, "%s",
+                   decode_boolean_bitfield(data2, 0x8000, 8*2,
+                       "Data length exceeds maximum frame size", NULL));
+       }
+       if (data2 & 0x4000) {
+               proto_tree_add_text(data2_tree, offset, 2, "%s",
+                   decode_boolean_bitfield(data2, 0x4000, 8*2,
+                       "Data length exceeds user's buffer", NULL));
+       }
+       proto_tree_add_text(data2_tree, offset, 2, "%s",
+           decode_numeric_bitfield(data2, 0x3FFF, 2*8,
+                       "Status data length = %u"));
+       nb_xmit_corrl(pd, offset, tree); 
+       if (!netbios_add_name("Receiver's Name", pd, offset + NB_RECVER_NAME,
+           tree))
+               return;
+       netbios_add_name("Sender's Name", pd, offset + NB_SENDER_NAME,
            tree);
 }
 
-static void  dissect_netb_session_init(const u_char *data_ptr, int offset,
+
+static void  dissect_netb_data_ack(const u_char *pd, int offset,
     frame_data *fd, proto_tree *tree)
 
-{/* Handle the SESSION INITIATE command */
+{/* Handle the DATA ACK command */
 
-       netbios_add_flags( data_ptr, tree, offset + NB_FLAGS);
+       nb_xmit_corrl(pd, offset, tree);
+       nb_remote_session(pd, offset, tree);
+       nb_local_session(pd, offset, tree);
+}
 
-       nb_data2( "Max data recv size: %d", 2, data_ptr, offset, tree); 
-       nb_resp_corrl( data_ptr, offset, tree);
-       nb_xmit_corrl( data_ptr, offset, tree); 
-       nb_remote_session( data_ptr, offset, tree); 
-       nb_local_session( data_ptr, offset, tree); 
+
+static void  dissect_netb_data_first_middle(const u_char *pd, int offset,
+    frame_data *fd, proto_tree *tree)
+
+{/* Handle the DATA FIRST MIDDLE command */
+
+       netbios_data_first_middle_flags(pd, tree, offset + NB_FLAGS);
+
+       nb_resync_indicator(pd, offset, tree);
+       nb_xmit_corrl(pd, offset, tree);
+       nb_resp_corrl(pd, offset, tree);
+       nb_remote_session(pd, offset, tree);
+       nb_local_session(pd, offset, tree);
 }
 
 
-static void  dissect_netb_session_confirm(const u_char *data_ptr, int offset,
+static void  dissect_netb_data_only_last(const u_char *pd, int offset,
+    frame_data *fd, proto_tree *tree)
+
+{/* Handle the DATA ONLY LAST command */
+
+       netbios_data_only_flags(pd, tree, offset + NB_FLAGS);
+
+       nb_resync_indicator(pd, offset, tree);
+       nb_xmit_corrl(pd, offset, tree);
+       nb_resp_corrl(pd, offset, tree);
+       nb_remote_session(pd, offset, tree);
+       nb_local_session(pd, offset, tree);
+}
+
+
+static void  dissect_netb_session_confirm(const u_char *pd, int offset,
     frame_data *fd, proto_tree *tree)
 
 {/* Handle the SESSION CONFIRM command */
 
-       netbios_add_ses_confirm_flags( data_ptr, tree, offset + NB_FLAGS);
+       netbios_add_ses_confirm_flags(pd, tree, offset + NB_FLAGS);
 
-       nb_data2( "Max data recv size: %d", 2, data_ptr, offset, tree); 
-       nb_resp_corrl( data_ptr, offset, tree);
-       nb_xmit_corrl( data_ptr, offset, tree); 
-       nb_remote_session( data_ptr, offset, tree); 
-       nb_local_session( data_ptr, offset, tree); 
+       nb_data2("Max data recv size: %u", 2, pd, offset, tree);
+       nb_xmit_corrl(pd, offset, tree);
+       nb_resp_corrl(pd, offset, tree);
+       nb_remote_session(pd, offset, tree);
+       nb_local_session(pd, offset, tree);
 }
 
 
-static void  dissect_netb_data_only_last(const u_char *data_ptr, int offset,
+static void  dissect_netb_session_end(const u_char *pd, int offset,
     frame_data *fd, proto_tree *tree)
 
-{/* Handle the DATA ONLY LAST command */
+{/* Handle the SESSION END command */
+       guint16 termination_indicator = pletohs(&pd[offset + NB_DATA2]);
+
+       switch (termination_indicator) {
 
-       netbios_data_only_flags( data_ptr, tree, offset + NB_FLAGS);
+       case 0x0000:
+               proto_tree_add_text( tree, offset + NB_DATA2, 2,
+                   "Termination indicator: Normal session end");
+               break;
 
-       nb_data2( "Re-sync indicator: %d", 2, data_ptr, offset, tree); 
-       nb_resp_corrl( data_ptr, offset, tree);
-       nb_remote_session( data_ptr, offset, tree); 
-       nb_local_session( data_ptr, offset, tree); 
+       case 0x0001:
+               proto_tree_add_text( tree, offset + NB_DATA2, 2,
+                   "Termination indicator: Abormal session end");
+               break;
 
+       default:
+               proto_tree_add_text( tree, offset + NB_DATA2, 2,
+                   "Termination indicator: 0x%04x (should be 0x0000 or 0x0001)",
+                   termination_indicator);
+               break;
+       }
+
+       nb_remote_session(pd, offset, tree);
+       nb_local_session(pd, offset, tree);
 }
 
 
-static void  dissect_netb_datagram(const u_char *data_ptr, int offset,
+static void  dissect_netb_session_init(const u_char *pd, int offset,
     frame_data *fd, proto_tree *tree)
 
-{/* Handle the DATAGRAM command */
+{/* Handle the SESSION INITIALIZE command */
 
-       nb_data1( "Data1: 0x%02x", data_ptr, offset, tree); 
-       nb_data2( "Data2: 0x%04x", 2, data_ptr, offset, tree); 
-       nb_xmit_corrl( data_ptr, offset, tree);
-       nb_resp_corrl( data_ptr, offset, tree);
-       netbios_add_name( "Receiver's Name", data_ptr, offset, NB_RECVER_NAME,
-           tree);
-       netbios_add_name( "Sender's Name", data_ptr, offset, NB_SENDER_NAME,
-           tree);
+       netbios_add_session_init_flags(pd, tree, offset + NB_FLAGS);
 
+       nb_data2("Max data recv size: %u", 2, pd, offset, tree);
+       nb_resp_corrl(pd, offset, tree);
+       nb_xmit_corrl(pd, offset, tree);
+       nb_remote_session(pd, offset, tree);
+       nb_local_session(pd, offset, tree);
 }
 
-static void  dissect_netb_data_ack(const u_char *data_ptr, int offset,
+
+static void  dissect_netb_no_receive(const u_char *pd, int offset,
     frame_data *fd, proto_tree *tree)
 
-{/* Handle the DATA ACK command */
+{/* Handle the NO RECEIVE command */
 
-       netbios_data_only_flags( data_ptr, tree, offset + NB_FLAGS);
+       netbios_no_receive_flags(pd, tree, offset + NB_FLAGS);
+
+       nb_data2("Number of data bytes accepted: %u", 2, pd, offset, tree);
+       nb_remote_session(pd, offset, tree);
+       nb_local_session(pd, offset, tree);
+}
 
 
-       nb_xmit_corrl( data_ptr, offset, tree);
-       nb_remote_session( data_ptr, offset, tree); 
-       nb_local_session( data_ptr, offset, tree); 
+static void  dissect_netb_receive_outstanding(const u_char *pd, int offset,
+    frame_data *fd, proto_tree *tree)
 
+{/* Handle the RECEIVE OUTSTANDING command */
+
+       nb_data2("Number of data bytes accepted: %u", 2, pd, offset, tree);
+       nb_remote_session(pd, offset, tree);
+       nb_local_session(pd, offset, tree);
+}
+
+
+static void  dissect_netb_receive_continue(const u_char *pd, int offset,
+    frame_data *fd, proto_tree *tree)
+
+{/* Handle the RECEIVE CONTINUE command */
+
+       nb_xmit_corrl(pd, offset, tree);
+       nb_remote_session(pd, offset, tree);
+       nb_local_session(pd, offset, tree);
 }
 
 
@@ -537,37 +924,37 @@ static void  dissect_netb_data_ack(const u_char *data_ptr, int offset,
 
 void (*dissect_netb[])(const u_char *, int, frame_data *, proto_tree *) = {
 
-  dissect_netb_add_group,              /* add_group    0x00 */
-  dissect_netb_add_name,       /* add_name     0x01 */
-  dissect_netb_unknown,                /* unknown      0x02 */
-  dissect_netb_unknown,                /* unknown      0x03 */
-  dissect_netb_unknown,                /* unknown      0x04 */
-  dissect_netb_unknown,                /* unknown      0x05 */
-  dissect_netb_unknown,                /* unknown      0x06 */
-  dissect_netb_unknown,                /* unknown      0x07 */
-  dissect_netb_datagram,       /* Datagram     0x08 */
-  dissect_netb_unknown,                /* unknown      0x09 */
-  dissect_netb_name_query,     /* Name Query   0x0A */
-  dissect_netb_unknown,                /* unknown      0x0B */
-  dissect_netb_unknown,                /* unknown      0x0C */
-  dissect_netb_unknown,                /* unknown      0x0D */
-  dissect_netb_name_resp,      /* Name Resp    0x0E */
-  dissect_netb_unknown,                /* unknown      0x0F */
-  dissect_netb_unknown,                /* unknown      0x10 */
-  dissect_netb_unknown,                /* unknown      0x11 */
-  dissect_netb_unknown,                /* unknown      0x12 */
-  dissect_netb_unknown,                /* unknown      0x13 */
-  dissect_netb_data_ack,       /* Data Ack     0x14 */
-  dissect_netb_unknown,                /* unknown      0x15 */
-  dissect_netb_data_only_last, /* Data Only Last 0x16 */
-  dissect_netb_session_confirm,        /* Session Confirm 0x17 */
-  dissect_netb_unknown,                /* unknown      0x18 */
-  dissect_netb_session_init,   /* Session Initialize 0x19      */
-  dissect_netb_unknown,                /* unknown      0x1A */
-  dissect_netb_unknown,                /* unknown      0x1B */
-  dissect_netb_unknown,                /* unknown      0x1C */
-  dissect_netb_unknown,                /* unknown      0x1D */
-  dissect_netb_unknown,                /* unknown      0x1E */
+  dissect_netb_add_group_name, /* Add Group Name       0x00 */
+  dissect_netb_add_name,       /* Add Name             0x01 */
+  dissect_netb_name_in_conflict,/* Name In Conflict    0x02 */
+  dissect_netb_status_query,   /* Status Query         0x03 */
+  dissect_netb_unknown,                /* unknown              0x04 */
+  dissect_netb_unknown,                /* unknown              0x05 */
+  dissect_netb_unknown,                /* unknown              0x06 */
+  dissect_netb_unknown,                /* Terminate Trace      0x07 */
+  dissect_netb_datagram,       /* Datagram             0x08 */
+  dissect_netb_datagram_bcast, /* Datagram Broadcast   0x09 */
+  dissect_netb_name_query,     /* Name Query           0x0A */
+  dissect_netb_unknown,                /* unknown              0x0B */
+  dissect_netb_unknown,                /* unknown              0x0C */
+  dissect_netb_add_name_resp,  /* Add Name Response    0x0D */
+  dissect_netb_name_resp,      /* Name Recognized      0x0E */
+  dissect_netb_status_resp,    /* Status Response      0x0F */
+  dissect_netb_unknown,                /* unknown              0x10 */
+  dissect_netb_unknown,                /* unknown              0x11 */
+  dissect_netb_unknown,                /* unknown              0x12 */
+  dissect_netb_unknown,                /* Terminate Trace      0x13 */
+  dissect_netb_data_ack,       /* Data Ack             0x14 */
+  dissect_netb_data_first_middle,/* Data First Middle  0x15 */
+  dissect_netb_data_only_last, /* Data Only Last       0x16 */
+  dissect_netb_session_confirm,        /* Session Confirm      0x17 */
+  dissect_netb_session_end,    /* Session End          0x18 */
+  dissect_netb_session_init,   /* Session Initialize   0x19 */
+  dissect_netb_no_receive,     /* No Receive           0x1A */
+  dissect_netb_receive_outstanding,/* Receive Outstanding 0x1B */
+  dissect_netb_receive_continue,/* Receive Continue    0x1C */
+  dissect_netb_unknown,                /* unknown              0x1D */
+  dissect_netb_unknown,                /* unknown              0x1E */
 
   dissect_netb_unknown,                /* Session Alive        0x1f (nothing to do) */
 };
@@ -577,23 +964,19 @@ void dissect_netbios(const u_char *pd, int offset, frame_data *fd,
     proto_tree *tree)
 
 {
-       const u_char            *nb_data_ptr;
        proto_tree              *netb_tree;
        proto_item              *ti;
        guint16                 hdr_len, command;
-       char                    name[17];
-
-       nb_data_ptr = &pd[offset];
+       char                    name[(NETBIOS_NAME_LEN - 1)*4 + 1];
+       int                     name_type;
 
 /* Find NetBIOS marker EFFF, this is done because I have seen an extra LLC */
 /* byte on our network. This only checks for one extra LLC byte. */
 
-       if (( *(nb_data_ptr + 2) != 0xff) || ( *(nb_data_ptr + 3) != 0xef)){
-
-               ++nb_data_ptr;          /** marker not found shift one byte */
+       if (( pd[offset + 2] != 0xff) || ( pd[offset + 3] != 0xef)){
                ++offset;
-               if (( *(nb_data_ptr + 2) != 0xff)
-                   || ( *(nb_data_ptr + 3) != 0xef)){
+               if (( pd[offset + 2] != 0xff)
+                   || ( pd[offset + 3] != 0xef)){
                        if (check_col(fd, COL_PROTOCOL))
                                col_add_str(fd, COL_PROTOCOL, "NetBIOS");       
        
@@ -603,7 +986,7 @@ void dissect_netbios(const u_char *pd, int offset, frame_data *fd,
                        if (tree) {
                                ti = proto_tree_add_item(tree, proto_netbios,
                                        offset, END_OF_FRAME, NULL);
-                               netb_tree = proto_item_add_subtree(ti, ETT_NETB);
+                               netb_tree = proto_item_add_subtree(ti, ett_netb);
                                
                                proto_tree_add_text( netb_tree, offset,
                                    END_OF_FRAME, "Data (%u bytes)", 
@@ -615,40 +998,40 @@ void dissect_netbios(const u_char *pd, int offset, frame_data *fd,
        
        /* To do: check for runts, errs, etc. */
 
-       hdr_len = pletohs( nb_data_ptr + NB_LENGTH);
-       command = *(nb_data_ptr + NB_COMMAND);
-
-       
-       if ( command == NB_NAME_QUERY ) {
-               get_netbios_name( pd, offset + 12, name);
-       }               
-
-       if ( command == NB_NAME_RESP ){
-               get_netbios_name( pd, offset + 28, name);
-       }               
+       hdr_len = pletohs(&pd[offset + NB_LENGTH]);
+       command = pd[offset + NB_COMMAND];
        
-
        if (check_col(fd, COL_PROTOCOL))
                col_add_str(fd, COL_PROTOCOL, "NetBIOS");
 
        if (check_col(fd, COL_INFO)) {                  /* print command name */
-               if ( command == NB_NAME_QUERY)
-                       col_add_fstr(fd, COL_INFO, "%s for %s",
-                           CommandName[ command], name);
+               switch ( command ) {
+               case NB_NAME_QUERY:
+                       name_type = get_netbios_name( pd, offset + 12, name);
+                       col_add_fstr(fd, COL_INFO, "%s for %s<%02x>",
+                           CommandName[ command], name, name_type);
+                       break;
 
-               else if ( command == NB_NAME_RESP)
-                       col_add_fstr(fd, COL_INFO, "%s - %s",
-                           CommandName[ command], name);
+               case NB_NAME_RESP:
+                       name_type = get_netbios_name( pd, offset + 28, name);
+                       col_add_fstr(fd, COL_INFO, "%s - %s<%02x>",
+                           CommandName[ command], name, name_type);
+                       break;
 
-               else
-                       col_add_fstr(fd, COL_INFO, "%s", CommandName[ command]);
+               default:
+                       if ( command < sizeof( dissect_netb)/ sizeof(void *))
+                               col_add_fstr(fd, COL_INFO, "%s", CommandName[ command]);
+                       else
+                               col_add_fstr(fd, COL_INFO, "Unknown");
+                       break;
+               }
        }
 
 
        if (tree) {
                ti = proto_tree_add_item(tree, proto_netbios, offset, END_OF_FRAME, NULL);
 
-               netb_tree = proto_item_add_subtree(ti, ETT_NETB);
+               netb_tree = proto_item_add_subtree(ti, ett_netb);
 
                proto_tree_add_text(netb_tree, offset, 2,
                                "Header Length: %d", hdr_len);
@@ -663,21 +1046,21 @@ void dissect_netbios(const u_char *pd, int offset, frame_data *fd,
                if ( command < sizeof( dissect_netb)/ sizeof(void *))
 
                                                /* branch to handle commands */
-                       (dissect_netb[ command])( nb_data_ptr, offset, fd,
+                       (dissect_netb[ command])( pd, offset, fd,
                                netb_tree);             
        }
 
                                                        /* Test for SMB data */
        if ( (END_OF_FRAME) > ( hdr_len + 4)){          /* if enough data */
 
-               nb_data_ptr += hdr_len;                 /* move past header */
+               offset += hdr_len;                      /* move past header */
 
-               if (( *nb_data_ptr == 0xff) &&          /* if SMB marker */
-                   ( *(nb_data_ptr + 1) == 'S') &&
-                   ( *(nb_data_ptr + 2) == 'M') &&
-                   ( *(nb_data_ptr + 3) == 'B'))
+               if (( pd[offset + 0] == 0xff) &&        /* if SMB marker */
+                   ( pd[offset + 1] == 'S') &&
+                   ( pd[offset + 2] == 'M') &&
+                   ( pd[offset + 3] == 'B'))
                                                        /* decode SMB */
-                       dissect_smb(pd, offset + hdr_len, fd, tree, 
+                       dissect_smb(pd, offset, fd, tree, 
                                END_OF_FRAME - hdr_len);
        }
 
@@ -688,6 +1071,13 @@ void dissect_netbios(const u_char *pd, int offset, frame_data *fd,
 
 void proto_register_netbios(void)
 {
+       static gint *ett[] = {
+               &ett_netb,
+               &ett_netb_name,
+               &ett_netb_flags,
+               &ett_netb_status,
+       };
 
         proto_netbios = proto_register_protocol("NetBIOS", "netbios");
+       proto_register_subtree_array(ett, array_length(ett));
 }