From Didier Gautheron:
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 3 May 2002 21:25:43 +0000 (21:25 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 3 May 2002 21:25:43 +0000 (21:25 +0000)
    afp :
more calls.
    asp :
move release transaction to atp.
dissect asp call.
fix a bug with transaction handling (conversation +tid are not
enough as key ).
    atp :
deal with one packet transaction without ATP_EOM.
    dsi:
safeguard against overflow for unreassembled packet.
more flags decoded.

Update the "packet-atalk.c" comment to reflect all the protocols in it.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@5376 f5534014-38df-0310-8fa8-9805f1628bb7

packet-afp.c
packet-afp.h
packet-atalk.c
packet-dsi.c

index 9061f7e80fe04e0464c97d4be4042bdb131c9809..7796c2cb743f742e04e535fc5393d6eba5237469 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for afp packet dissection
  * Copyright 2002, Didier Gautheron <dgautheron@magic.fr>
  *
- * $Id: packet-afp.c,v 1.13 2002/05/01 10:01:42 guy Exp $
+ * $Id: packet-afp.c,v 1.14 2002/05/03 21:25:43 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -273,9 +273,11 @@ static gint ett_afp_dir_ar = -1;
 
 static gint ett_afp_server_vol         = -1;
 static gint ett_afp_vol_list           = -1;
+static gint ett_afp_vol_flag           = -1;
 static gint ett_afp_cat_search                 = -1;
 static gint ett_afp_cat_r_bitmap       = -1;
 static gint ett_afp_cat_spec           = -1;
+static gint ett_afp_vol_did    = -1;
 
 static dissector_handle_t data_handle;
 
@@ -1371,8 +1373,10 @@ dissect_reply_afp_get_server_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_
        guint8 flag;
        guint8 i;
        proto_tree *sub_tree = NULL;
+       proto_tree *flag_tree;
        proto_item *item;
-
+       proto_item *ti;
+       
        if (!tree)
                return offset;
 
@@ -1391,11 +1395,11 @@ dissect_reply_afp_get_server_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_
                tree = proto_item_add_subtree(item, ett_afp_vol_list);
 
                flag = tvb_get_guint8(tvb, offset);
-               proto_tree_add_text(tree, tvb, offset , 1,"Flags : 0x%02x", flag);
-#if 0
-               /* FIXME */
-               hf_afp_vol_flag_passwd hf_afp_vol_flag_unix_priv 
-#endif         
+
+               ti = proto_tree_add_text(tree, tvb, offset , 1,"Flags : 0x%02x", flag);
+               flag_tree = proto_item_add_subtree(ti, ett_afp_vol_flag);
+               proto_tree_add_item(flag_tree, hf_afp_vol_flag_passwd, tvb, offset, 1,FALSE);
+               proto_tree_add_item(flag_tree, hf_afp_vol_flag_unix_priv ,tvb, offset, 1,FALSE);
                offset++;
 
                len  = tvb_get_guint8(tvb, offset) +1;
@@ -2094,6 +2098,33 @@ dissect_query_afp_move(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint
        return offset;
 }
 
+/* ************************** */
+static gint
+dissect_query_afp_copy_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       proto_tree *sub_tree = NULL;
+       proto_item *item;
+               
+       PAD(1);
+       if (tree) {
+               item = proto_tree_add_text(tree, tvb, offset, 6,"Source volume");
+               sub_tree = proto_item_add_subtree(item, ett_afp_vol_did);
+       }
+       offset = decode_vol_did(sub_tree, tvb, offset);
+
+       if (tree) {
+               item = proto_tree_add_text(tree, tvb, offset, 6,"Dest volume");
+               sub_tree = proto_item_add_subtree(item, ett_afp_vol_did);
+       }
+       offset = decode_vol_did(sub_tree, tvb, offset);
+
+       offset = decode_name_label(tree, pinfo, tvb, offset, "Source path: %s");
+       offset = decode_name_label(tree, NULL, tvb, offset,  "Dest dir:    %s");
+       offset = decode_name_label(tree, NULL, tvb, offset,  "New name:    %s");
+
+       return offset;
+}
+
 /* ************************** */
 static gint
 dissect_query_afp_rename(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
@@ -2226,15 +2257,6 @@ dissect_query_afp_get_icon(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tr
        return offset;
 }
 
-/* -------------------------- 
-       fallback to data in afp dissector
-*/
-static gint
-dissect_reply_afp_get_icon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
-{
-       return offset;
-}
-
 /* ************************** */
 static gint
 dissect_query_afp_get_icon_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
@@ -2440,6 +2462,8 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        }
 
        if (!request_val) {     /* missing request */
+               if (check_col(pinfo->cinfo, COL_INFO)) 
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "[Reply without query?]");
                return;
        }
 
@@ -2475,7 +2499,7 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                case AFP_CLOSEFORK:
                        offset = dissect_query_afp_with_fork(tvb, pinfo, afp_tree, offset);break;
                case AFP_COPYFILE:
-                       /* offset = dissect_query_afp_copy_file(tvb, pinfo, afp_tree, offset);break; */
+                       offset = dissect_query_afp_copy_file(tvb, pinfo, afp_tree, offset);break; 
                case AFP_CREATEFILE:
                        offset = dissect_query_afp_create_file(tvb, pinfo, afp_tree, offset);break; 
                case AFP_ENUMERATE:
@@ -2536,7 +2560,7 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                        break;
                case AFP_CATSEARCH:
                        offset = dissect_query_afp_cat_search(tvb, pinfo, afp_tree, offset);break; 
-               case AFP_GETICON:
+               case AFP_GETICON:       
                        offset = dissect_query_afp_get_icon(tvb, pinfo, afp_tree, offset);break; 
                case AFP_GTICNINFO:
                        offset = dissect_query_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break; 
@@ -2590,8 +2614,6 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                        offset = dissect_reply_afp_open_dt(tvb, pinfo, afp_tree, offset);break;
                case AFP_CATSEARCH:
                        offset = dissect_reply_afp_cat_search(tvb, pinfo, afp_tree, offset);break; 
-               case AFP_GETICON:
-                       offset = dissect_reply_afp_get_icon(tvb, pinfo, afp_tree, offset);break; 
                case AFP_GTICNINFO:
                        offset = dissect_reply_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break; 
                case AFP_GETAPPL:
@@ -3031,6 +3053,16 @@ proto_register_afp(void)
        FT_UINT_STRING, BASE_NONE, NULL, 0x0,
        "Volume name", HFILL }},
 
+    { &hf_afp_vol_flag_passwd,
+      { "Password",         "afp.vol_flag_passwd",
+           FT_BOOLEAN, 8, NULL,  1,
+       "Volume is password-protected", HFILL }},
+
+    { &hf_afp_vol_flag_unix_priv,
+      { "Unix privs",         "afp.vol_flag_unix_priv",
+           FT_BOOLEAN, 8, NULL,  2,
+       "Volume has unix privileges", HFILL }},
+
     { &hf_afp_vol_id,
       { "Volume id",         "afp.vol_id",
                FT_UINT16, BASE_DEC, NULL, 0x0,
@@ -3212,7 +3244,7 @@ proto_register_afp(void)
        "First structure returned", HFILL }},
 
     { &hf_afp_file_flag,
-      { "Dir",         "afp.flag",
+      { "Dir",         "afp.file_flag",
                FT_BOOLEAN, 8, NULL, 0x80,
        "Is a dir", HFILL }},
 
@@ -3497,6 +3529,7 @@ proto_register_afp(void)
        &ett_afp,
        &ett_afp_server_vol,
        &ett_afp_vol_list,
+       &ett_afp_vol_flag,
        &ett_afp_vol_bitmap,
        &ett_afp_vol_attribute,
        &ett_afp_dir_bitmap,
@@ -3513,6 +3546,7 @@ proto_register_afp(void)
        &ett_afp_cat_search,
        &ett_afp_cat_r_bitmap,
        &ett_afp_cat_spec,
+       &ett_afp_vol_did,
   };
 
   proto_afp = proto_register_protocol("AppleTalk Filing Protocol", "AFP", "afp");
index 0efd8ebc5c563228adadfdf19f1dfdf0c56b5ce6..c15fd06c28d27358030b8b76bf4adc11ebdb3474 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-afp.h
  * Definitions for packet disassembly structures and routines
  *
- * $Id: packet-afp.h,v 1.3 2002/04/30 22:05:33 guy Exp $
+ * $Id: packet-afp.h,v 1.4 2002/05/03 21:25:43 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -79,9 +79,6 @@
 extern const value_string asp_error_vals[];
 extern const value_string afp_server_addr_type_vals[];
 
-extern gint 
-dissect_asp_reply_get_status(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset);
-
 /* server flags */
 #define AFPSRVRINFO_COPY         (1<<0)  /* supports copyfile */
 #define AFPSRVRINFO_PASSWD       (1<<1)  /* supports change password */
@@ -90,6 +87,8 @@ dissect_asp_reply_get_status(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
 #define AFPSRVRINFO_SRVSIGNATURE (1<<4)  /* supports server signature */
 #define AFPSRVRINFO_TCPIP        (1<<5)  /* supports tcpip */
 #define AFPSRVRINFO_SRVNOTIFY    (1<<6)  /* supports server notifications */
+#define AFPSRVRINFO_SRVRECONNECT (1<<7)  /* supports reconnect */
+#define AFPSRVRINFO_SRVDIRECTORY (1<<8)  /* supports directory services */
 #define AFPSRVRINFO_FASTBOZO     (1<<15) /* fast copying */
 
 #define AFPSTATUS_MACHOFF     0
index 58b403ca65dc7a6926f13922061965346b16fdc5..893465e9a82100948ecc05a09bc499d776236aa1 100644 (file)
@@ -1,7 +1,8 @@
 /* packet-atalk.c
- * Routines for Appletalk packet disassembly (DDP, currently).
+ * Routines for AppleTalk packet disassembly: LLAP, DDP, NBP, ATP, ASP,
+ * RTMP.
  *
- * $Id: packet-atalk.c,v 1.69 2002/05/01 07:26:45 guy Exp $
+ * $Id: packet-atalk.c,v 1.70 2002/05/03 21:25:43 guy Exp $
  *
  * Simon Wilkinson <sxw@dcs.ed.ac.uk>
  *
@@ -38,6 +39,8 @@
 
 #include <glib.h>
 #include <epan/packet.h>
+#include <string.h>
+
 #include "etypes.h"
 #include "ppptypes.h"
 #include "aftypes.h"
@@ -120,6 +123,7 @@ static int hf_atp_treltimer = -1; /* bits 2,1,0  TRel timeout indicator */
 
 static int hf_atp_bitmap = -1;   /* u_int8_t  bitmap or sequence number */
 static int hf_atp_tid = -1;      /* u_int16_t transaction id. */
+static int hf_atp_user_bytes = -1;
 
 static int hf_atp_segments = -1;
 static int hf_atp_segment = -1;
@@ -158,16 +162,57 @@ static int hf_atp_segment_error = -1;
 static int proto_asp = -1;
 static int hf_asp_func = -1;
 static int hf_asp_error = -1;
+static int hf_asp_socket       = -1;
+static int hf_asp_version      = -1;
+static int hf_asp_session_id   = -1;
+static int hf_asp_zero_value   = -1;
+static int hf_asp_init_error   = -1;
+static int hf_asp_attn_code    = -1;
+static int hf_asp_seq          = -1;
+static int hf_asp_size         = -1;
+
+/* status stuff same for asp and afp */
+static int hf_asp_server_name = -1;
+static int hf_asp_server_type = -1;
+static int hf_asp_server_vers = -1;
+static int hf_asp_server_uams = -1;
+static int hf_asp_server_icon = -1;
+static int hf_asp_server_directory = -1;
+
+static int hf_asp_server_flag = -1;
+static int hf_asp_server_flag_copyfile = -1;
+static int hf_asp_server_flag_passwd   = -1;
+static int hf_asp_server_flag_no_save_passwd = -1;
+static int hf_asp_server_flag_srv_msg  = -1;
+static int hf_asp_server_flag_srv_sig  = -1;
+static int hf_asp_server_flag_tcpip    = -1;
+static int hf_asp_server_flag_notify   = -1;
+static int hf_asp_server_flag_reconnect        = -1;
+static int hf_asp_server_flag_directory        = -1;
+static int hf_asp_server_flag_fast_copy = -1;
+static int hf_asp_server_signature     = -1;
+
+static int hf_asp_server_addr_len      = -1;
+static int hf_asp_server_addr_type     = -1;
+static int hf_asp_server_addr_value    = -1;
+
+static gint ett_asp_status = -1;
+static gint ett_asp_uams   = -1;
+static gint ett_asp_vers   = -1;
+static gint ett_asp_addr   = -1;
+static gint ett_asp_directory = -1;
+static gint ett_asp_status_server_flag = -1;
 
 static guint asp_packet_init_count = 200;
 
 typedef struct {
        guint32 conversation;
+       guint8  src[4];
        guint16 seq;
 } asp_request_key;
  
 typedef struct {
-       guint8  command;
+       guint8  value;  /* command for asp, bitmap for atp */
 } asp_request_val;
  
 static GHashTable *asp_request_hash = NULL;
@@ -181,7 +226,8 @@ static gint  asp_equal (gconstpointer v, gconstpointer v2)
        asp_request_key *val2 = (asp_request_key*)v2;
 
        if (val1->conversation == val2->conversation &&
-                       val1->seq == val2->seq) {
+                       val1->seq == val2->seq &&
+                       !memcmp(val1->src, val2->src, 4)) {
                return 1;
        }
        return 0;
@@ -193,6 +239,12 @@ static guint asp_hash  (gconstpointer v)
         return asp_key->seq;
 }
 
+/* ------------------------------------ */
+static GHashTable *atp_request_hash = NULL;
+static GMemChunk *atp_request_keys = NULL;
+static GMemChunk *atp_request_vals = NULL;
+
+
 /* ------------------------------------ */
 static int proto_nbp = -1;
 static int hf_nbp_op = -1;
@@ -669,13 +721,19 @@ dissect_atp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
   guint8 frag_number = 0;
   guint op;
   guint16 tid;
+  guint8 query;
   struct aspinfo aspinfo;
   tvbuff_t   *new_tvb = NULL;
   gboolean save_fragmented;
   gboolean more_fragment = FALSE;
   int len;
   guint8 bitmap;
-  
+  guint8 nbe = 0;
+  guint8 t = 0;
+  conversation_t       *conversation;
+  asp_request_key request_key, *new_request_key;
+  asp_request_val *request_val;
+
   if (check_col(pinfo->cinfo, COL_PROTOCOL))
     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATP");
 
@@ -683,21 +741,54 @@ dissect_atp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
   bitmap   = tvb_get_guint8(tvb, offset +1);
   tid      = tvb_get_ntohs(tvb, offset +2);
 
+  t = bitmap;
+  while(t) {
+       nbe++;
+       t >>= 1;
+  }
+
   op = ctrlinfo >> 6;
 
   aspinfo.reply   = (0x80 == (ctrlinfo & ATP_FUNCMASK))?1:0;
   aspinfo.release = (0xC0 == (ctrlinfo & ATP_FUNCMASK))?1:0;
   aspinfo.seq = tid;
   aspinfo.code = 0;
+  query = (!aspinfo.reply && !aspinfo.release);
+
+  conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+               pinfo->srcport, pinfo->destport, 0);
 
-  /* FIXME
+  if (conversation == NULL)
+  {
+       conversation = conversation_new(&pinfo->src, &pinfo->dst,
+                       pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+  }
+
+  request_key.conversation = conversation->index;
+  memcpy(request_key.src, (!aspinfo.reply)?pinfo->src.data:pinfo->dst.data, 4);
+  request_key.seq = aspinfo.seq;
+
+  request_val = (asp_request_val *) g_hash_table_lookup(atp_request_hash, &request_key);
+
+  if (!request_val && query )  {
+        new_request_key = g_mem_chunk_alloc(atp_request_keys);
+        *new_request_key = request_key;
+
+        request_val = g_mem_chunk_alloc(atp_request_vals);
+        request_val->value = nbe;
+
+        g_hash_table_insert(atp_request_hash, new_request_key,request_val);
+  }
+
+  /* 
      ATP_EOM is not mandatory. Some implementations don't always set it
      if the query is only one packet.
        
-     need to keep bitmap from request.
+     So it needs to keep the number of packets asked in request.
     */         
+
   if (aspinfo.reply) {
-     more_fragment = !(ATP_EOM & ctrlinfo); /* or only one segment in transaction request */
+     more_fragment = !((ATP_EOM & ctrlinfo) || (request_val && 1 == request_val->value));
      frag_number = bitmap;
   }
   
@@ -712,7 +803,7 @@ dissect_atp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
   if (tree) {
     ti = proto_tree_add_item(tree, proto_atp, tvb, offset, -1, FALSE);
     atp_tree = proto_item_add_subtree(ti, ett_atp);
-    proto_item_set_len(atp_tree, ATP_HDRSIZE -1);
+    proto_item_set_len(atp_tree, aspinfo.release?8:ATP_HDRSIZE -1);
 
     info_item = proto_tree_add_item(atp_tree, hf_atp_ctrlinfo, tvb, offset, 1, FALSE);
     atp_info_tree = proto_item_add_subtree(info_item, ett_atp_info);
@@ -725,15 +816,7 @@ dissect_atp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
       /* TReq with XO set */
       proto_tree_add_item(atp_info_tree, hf_atp_treltimer, tvb, offset, 1, FALSE);
     }
-
-    if (!aspinfo.reply) {
-      guint8 nbe = 0;
-      guint8 t = bitmap;
-               
-      while(t) {
-       nbe++;
-       t >>= 1;
-      }
+    if (query) {
       proto_tree_add_text(atp_tree, tvb, offset +1, 1,
                          "Bitmap: 0x%02x  %d packet(s) max", bitmap, nbe);
     }
@@ -741,7 +824,15 @@ dissect_atp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
       proto_tree_add_item(atp_tree, hf_atp_bitmap, tvb, offset +1, 1, FALSE);
     }
     proto_tree_add_item(atp_tree, hf_atp_tid, tvb, offset +2, 2, FALSE);
+
+    if (aspinfo.release)
+       proto_tree_add_item(atp_tree, hf_atp_user_bytes, tvb, offset +4, 4, FALSE);
+    
   }
+
+  if (aspinfo.release)
+       return;
+
   save_fragmented = pinfo->fragmented;
 
   /* FIXME 
@@ -796,7 +887,157 @@ dissect_atp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
   return;
 }
 
+/*
+       copy and past from dsi 
+*/
+static gint 
+dissect_asp_reply_get_status(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+        proto_tree      *sub_tree;
+       proto_item      *ti;
+
+       guint16 ofs;
+       guint16 flag;
+       guint16 sign_ofs = 0;
+       guint16 adr_ofs = 0;
+       guint16 dir_ofs = 0;
+       guint8  nbe;
+       guint8  len;
+       guint8  i;
+
+       if (!tree)
+               return offset;
+               
+       ti = proto_tree_add_text(tree, tvb, offset, -1, "Get Status");
+       tree = proto_item_add_subtree(ti, ett_asp_status);
+
+       ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF);
+       proto_tree_add_text(tree, tvb, offset +AFPSTATUS_MACHOFF, 2, "Machine offset: %d", ofs);
+
+       ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF);
+       proto_tree_add_text(tree, tvb, offset +AFPSTATUS_VERSOFF, 2, "Version offset: %d", ofs);
+
+       ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF);
+       proto_tree_add_text(tree, tvb, offset +AFPSTATUS_UAMSOFF, 2, "UAMS offset: %d", ofs);
+
+       ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF);
+       proto_tree_add_text(tree, tvb, offset +AFPSTATUS_ICONOFF, 2, "Icon offset: %d", ofs);
+
+       ofs = offset +AFPSTATUS_FLAGOFF;
+       ti = proto_tree_add_item(tree, hf_asp_server_flag, tvb, ofs, 2, FALSE);
+       sub_tree = proto_item_add_subtree(ti, ett_asp_status_server_flag);
+       proto_tree_add_item(sub_tree, hf_asp_server_flag_copyfile      , tvb, ofs, 2, FALSE);
+       proto_tree_add_item(sub_tree, hf_asp_server_flag_passwd        , tvb, ofs, 2, FALSE);
+       proto_tree_add_item(sub_tree, hf_asp_server_flag_no_save_passwd, tvb, ofs, 2, FALSE);
+       proto_tree_add_item(sub_tree, hf_asp_server_flag_srv_msg       , tvb, ofs, 2, FALSE);
+       proto_tree_add_item(sub_tree, hf_asp_server_flag_srv_sig       , tvb, ofs, 2, FALSE);
+       proto_tree_add_item(sub_tree, hf_asp_server_flag_tcpip         , tvb, ofs, 2, FALSE);
+       proto_tree_add_item(sub_tree, hf_asp_server_flag_notify        , tvb, ofs, 2, FALSE);
+       proto_tree_add_item(sub_tree, hf_asp_server_flag_reconnect     , tvb, ofs, 2, FALSE);
+       proto_tree_add_item(sub_tree, hf_asp_server_flag_directory     , tvb, ofs, 2, FALSE);
+       proto_tree_add_item(sub_tree, hf_asp_server_flag_fast_copy     , tvb, ofs, 2, FALSE);
+
+       proto_tree_add_item(tree, hf_asp_server_name, tvb, offset +AFPSTATUS_PRELEN, 1, FALSE);
+
+       flag = tvb_get_ntohs(tvb, ofs);
+       if ((flag & AFPSRVRINFO_SRVSIGNATURE)) {
+               ofs = offset +AFPSTATUS_PRELEN +tvb_get_guint8(tvb, offset +AFPSTATUS_PRELEN);
+               if ((ofs & 1))
+                       ofs++;
+
+               sign_ofs = tvb_get_ntohs(tvb, ofs);
+               proto_tree_add_text(tree, tvb, ofs, 2, "Signature offset: %d", sign_ofs);
+               sign_ofs += offset;
+
+               if ((flag & AFPSRVRINFO_TCPIP)) {
+                       ofs += 2;
+                       adr_ofs =  tvb_get_ntohs(tvb, ofs);
+                       proto_tree_add_text(tree, tvb, ofs, 2, "Network address offset: %d", adr_ofs);
+                       adr_ofs += offset;
+               }
+
+               if ((flag & AFPSRVRINFO_SRVDIRECTORY)) {
+                       ofs += 2;
+                       dir_ofs =  tvb_get_ntohs(tvb, ofs);
+                       proto_tree_add_text(tree, tvb, ofs, 2, "Directory services offset: %d", dir_ofs);
+                       dir_ofs += offset;
+               }
+       }
+               
+       ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF);
+       if (ofs)
+               proto_tree_add_item(tree, hf_asp_server_type, tvb, ofs, 1, FALSE);
+
+       ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF);
+       if (ofs) {
+               nbe = tvb_get_guint8(tvb, ofs);
+               ti = proto_tree_add_text(tree, tvb, ofs, 1, "Version list: %d", nbe);
+               ofs++;
+               sub_tree = proto_item_add_subtree(ti, ett_asp_vers);
+               for (i = 0; i < nbe; i++) {
+                       len = tvb_get_guint8(tvb, ofs) +1;
+                       proto_tree_add_item(sub_tree, hf_asp_server_vers, tvb, ofs, 1, FALSE);
+                       ofs += len;
+               }
+       }
+       
+       ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF);
+       if (ofs) {
+               nbe = tvb_get_guint8(tvb, ofs);
+               ti = proto_tree_add_text(tree, tvb, ofs, 1, "UAMS list: %d", nbe);
+               ofs++;
+               sub_tree = proto_item_add_subtree(ti, ett_asp_uams);
+               for (i = 0; i < nbe; i++) {
+                       len = tvb_get_guint8(tvb, ofs) +1;
+                       proto_tree_add_item(sub_tree, hf_asp_server_uams, tvb, ofs, 1, FALSE);
+                       ofs += len;
+               }
+       }
+
+       ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF);
+       if (ofs)
+               proto_tree_add_item(tree, hf_asp_server_icon, tvb, ofs, 256, FALSE);
 
+       if (sign_ofs) {
+               proto_tree_add_item(tree, hf_asp_server_signature, tvb, sign_ofs, 16, FALSE);
+       }
+
+       if (adr_ofs) {
+               ofs = adr_ofs;
+               nbe = tvb_get_guint8(tvb, ofs);
+               ti = proto_tree_add_text(tree, tvb, ofs, 1, "Address list: %d", nbe);
+               ofs++;
+               sub_tree = proto_item_add_subtree(ti, ett_asp_addr);
+               for (i = 0; i < nbe; i++) {
+                       len = tvb_get_guint8(tvb, ofs) -2;
+                       proto_tree_add_item(sub_tree, hf_asp_server_addr_len, tvb, ofs, 1, FALSE);
+                       ofs++;
+                       proto_tree_add_item(sub_tree, hf_asp_server_addr_type, tvb, ofs, 1, FALSE); 
+                       ofs++;
+                       proto_tree_add_item(sub_tree, hf_asp_server_addr_value,tvb, ofs, len, FALSE);
+                       ofs += len;
+               }
+       }
+       
+       if (dir_ofs) {
+               ofs = dir_ofs;
+               nbe = tvb_get_guint8(tvb, ofs);
+               ti = proto_tree_add_text(tree, tvb, ofs, 1, "Directory services list: %d", nbe);
+               ofs++;
+               sub_tree = proto_item_add_subtree(ti, ett_asp_directory);
+               for (i = 0; i < nbe; i++) {
+                       len = tvb_get_guint8(tvb, ofs) +1;
+                       proto_tree_add_item(sub_tree, hf_asp_server_directory, tvb, ofs, 1, FALSE);
+                       ofs += len;
+               }
+       }
+
+       return offset;
+}
+
+/* ----------------------------- 
+   ASP protocol cf. inside appletalk chap. 11
+*/
 static void
 dissect_asp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
 {
@@ -805,7 +1046,6 @@ dissect_asp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   proto_tree *asp_tree = NULL;
   proto_item *ti;
   guint8 fn;
-  gint32 error;
   int len;
   conversation_t       *conversation;
   asp_request_key request_key, *new_request_key;
@@ -826,18 +1066,19 @@ dissect_asp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   }
 
   request_key.conversation = conversation->index;      
+  memcpy(request_key.src, (!aspinfo->reply)?pinfo->src.data:pinfo->dst.data, 4);
   request_key.seq = aspinfo->seq;
 
   request_val = (asp_request_val *) g_hash_table_lookup(
                                                                asp_request_hash, &request_key);
 
-  if (!request_val && !aspinfo->reply && !aspinfo->release)  {
+  if (!request_val && !aspinfo->reply )  {
         fn = tvb_get_guint8(tvb, offset);
         new_request_key = g_mem_chunk_alloc(asp_request_keys);
         *new_request_key = request_key;
 
         request_val = g_mem_chunk_alloc(asp_request_vals);
-        request_val->command = fn;
+        request_val->value = fn;
 
         g_hash_table_insert(asp_request_hash, new_request_key,
                                                                request_val);
@@ -847,13 +1088,12 @@ dissect_asp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        return;
   }
 
-  fn = request_val->command;
+  fn = request_val->value;
+  aspinfo->command = fn;
 
   if (check_col(pinfo->cinfo, COL_INFO)) {
        if (aspinfo->reply)
                col_add_fstr(pinfo->cinfo, COL_INFO, "Reply tid %d",aspinfo->seq);
-       else if (aspinfo->release)
-               col_add_fstr(pinfo->cinfo, COL_INFO, "Release tid %d",aspinfo->seq);
        else
                col_add_fstr(pinfo->cinfo, COL_INFO, "Function: %s  tid %d",
                                val_to_str(fn, asp_func_vals, "Unknown (0x%01x)"), aspinfo->seq);
@@ -862,29 +1102,113 @@ dissect_asp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   if (tree) {
     ti = proto_tree_add_item(tree, proto_asp, tvb, offset, -1, FALSE);
     asp_tree = proto_item_add_subtree(ti, ett_asp);
-    if (!aspinfo->reply && !aspinfo->release) {
-      proto_tree_add_item(asp_tree, hf_asp_func, tvb, offset, 1, FALSE);
-    }
-    else { /* error code */
-      error = tvb_get_ntohl(tvb, offset);
-      if (error <= 0) 
-       proto_tree_add_item(asp_tree, hf_asp_error, tvb, offset, 4, FALSE);
-    }
   }
-  aspinfo->command = fn;
-  offset += 4;
-  len = tvb_reported_length_remaining(tvb,offset);
-  if (!aspinfo->release &&
-                  (fn == ASPFUNC_CMD || fn  == ASPFUNC_WRITE)) {
+  if (!aspinfo->reply) {
        tvbuff_t   *new_tvb;
+       /* let the called deal with asp_tree == NULL */
 
-       if (asp_tree)
-               proto_item_set_len(asp_tree, 4);
-       new_tvb = tvb_new_subset(tvb, offset,-1,len);
-       call_dissector(afp_handle, new_tvb, pinfo, tree);       
+       proto_tree_add_item(asp_tree, hf_asp_func, tvb, offset, 1, FALSE);
+       offset++;
+       switch(fn) {
+       case ASPFUNC_OPEN:
+               proto_tree_add_item(asp_tree, hf_asp_socket, tvb, offset, 1, FALSE);
+               offset++;
+               proto_tree_add_item(asp_tree, hf_asp_version, tvb, offset, 2, FALSE);
+               offset += 2;
+               break;                  
+       case ASPFUNC_TICKLE:
+       case ASPFUNC_CLOSE:
+               proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
+               offset++;
+               proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, FALSE);
+               offset +=2;
+               break;
+       case ASPFUNC_STAT:
+               proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, FALSE);
+               offset++;
+               proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, FALSE);
+               offset += 2;
+               break;          
+       case ASPFUNC_ATTN:
+               proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
+               offset++;
+               proto_tree_add_item(asp_tree, hf_asp_attn_code, tvb, offset, 2, FALSE);
+               offset +=2;
+               break;
+       case ASPFUNC_CMD:
+       case ASPFUNC_WRITE:
+               proto_item_set_len(asp_tree, 4);
+               proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
+               offset++;
+               proto_tree_add_item(asp_tree, hf_asp_seq, tvb, offset, 2, FALSE);
+               offset += 2;
+               len = tvb_reported_length_remaining(tvb,offset);
+               new_tvb = tvb_new_subset(tvb, offset,-1,len);
+               call_dissector(afp_handle, new_tvb, pinfo, tree);       
+               break;
+       case ASPFUNC_WRTCONT:
+               proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
+               offset++;
+               proto_tree_add_item(asp_tree, hf_asp_seq, tvb, offset, 2, FALSE);
+               offset += 2;
+               proto_tree_add_item(asp_tree, hf_asp_size, tvb, offset, 2, FALSE);
+               offset += 2;
+               break;
+       default:
+               proto_item_set_len(asp_tree, 4);
+               offset += 3;
+               len = tvb_reported_length_remaining(tvb,offset);
+               call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,len), pinfo, tree); 
+               break;
+       }
   }
-  else {       
-       call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,len), pinfo, tree); 
+  else {
+       tvbuff_t   *new_tvb;
+
+       proto_tree_add_uint(asp_tree, hf_asp_func, tvb, 0, 0, fn);
+       switch(fn) {
+       case ASPFUNC_OPEN:
+               proto_tree_add_item(asp_tree, hf_asp_socket, tvb, offset, 1, FALSE);
+               offset++;
+               proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
+               offset++;
+               proto_tree_add_item(asp_tree, hf_asp_init_error, tvb, offset, 2, FALSE);
+               offset += 2;
+               break;
+       case ASPFUNC_CLOSE:
+               proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, FALSE);
+               offset++;
+               proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, FALSE);
+               offset++;
+               proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, FALSE);
+               offset += 2;
+               break;          
+       case ASPFUNC_STAT:
+               proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 4, FALSE);
+               offset += 4;
+               dissect_asp_reply_get_status(tvb, pinfo, asp_tree, offset);
+               break;          
+       case ASPFUNC_CMD:
+       case ASPFUNC_WRITE:
+               proto_item_set_len(asp_tree, 4);
+               proto_tree_add_item(asp_tree, hf_asp_error, tvb, offset, 4, FALSE);
+               offset += 4;
+               len = tvb_reported_length_remaining(tvb,offset);
+               new_tvb = tvb_new_subset(tvb, offset,-1,len);
+               call_dissector(afp_handle, new_tvb, pinfo, tree);       
+               break;
+       case ASPFUNC_TICKLE:
+       case ASPFUNC_WRTCONT:
+               proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 4, FALSE);
+               /* fall */
+       case ASPFUNC_ATTN:      /* FIXME capture and spec disagree */
+       default:
+               proto_item_set_len(asp_tree, 4);
+               offset += 4;
+               len = tvb_reported_length_remaining(tvb,offset);
+               call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,len), pinfo, tree); 
+               break;
+       }
   }
 }
 
@@ -1083,10 +1407,29 @@ dissect_llap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 }
 
 static void
-atp_defragment_init(void)
+atp_init(void)
 {
-  fragment_table_init(&atp_fragment_table);
-  reassembled_table_init(&atp_reassembled_table);
+       /* fragment */
+       fragment_table_init(&atp_fragment_table);
+       reassembled_table_init(&atp_reassembled_table);
+       /* bitmap */
+       if (atp_request_hash)
+               g_hash_table_destroy(atp_request_hash);
+       if (atp_request_keys)
+               g_mem_chunk_destroy(atp_request_keys);
+       if (atp_request_vals)
+               g_mem_chunk_destroy(atp_request_vals);
+
+       atp_request_hash = g_hash_table_new(asp_hash, asp_equal);
+
+       atp_request_keys = g_mem_chunk_new("atp_request_keys",
+               sizeof(asp_request_key),
+               asp_packet_init_count * sizeof(asp_request_key),
+               G_ALLOC_AND_FREE);
+       atp_request_vals = g_mem_chunk_new("atp_request_vals",
+               sizeof(asp_request_val),
+               asp_packet_init_count * sizeof(asp_request_val),
+               G_ALLOC_AND_FREE);
 }
 
 static void 
@@ -1268,6 +1611,9 @@ proto_register_atalk(void)
     { &hf_atp_tid,
       { "TID",                 "atp.tid",      FT_UINT16,  BASE_DEC, 
                NULL, 0x0, "Transaction id", HFILL }},
+    { &hf_atp_user_bytes,
+      { "User bytes",                  "atp.user_bytes",       FT_UINT32,  BASE_HEX, 
+               NULL, 0x0, "User bytes", HFILL }},
 
     { &hf_atp_segment_overlap,
       { "Segment overlap",     "atp.segment.overlap", FT_BOOLEAN, BASE_NONE,
@@ -1308,6 +1654,136 @@ proto_register_atalk(void)
     { &hf_asp_error,
       { "asp error",           "asp.error",    FT_INT32,  BASE_DEC, 
                VALS(asp_error_vals), 0, "return error code", HFILL }},
+
+    { &hf_asp_version,
+      { "Version",             "asp.version",  FT_UINT16,  BASE_HEX, 
+               NULL, 0, "asp version", HFILL }},
+
+    { &hf_asp_attn_code,
+      { "Attn code",           "asp.attn_code",        FT_UINT16,  BASE_HEX, 
+               NULL, 0, "asp attention code", HFILL }},
+
+    { &hf_asp_init_error,
+      { "Error",               "asp.init_error",       FT_UINT16,  BASE_DEC, 
+               NULL, 0, "asp init error", HFILL }},
+
+    { &hf_asp_session_id,
+      { "Session ID",          "asp.session_id", FT_UINT8,  BASE_DEC, 
+               NULL, 0, "asp session id", HFILL }},
+
+    { &hf_asp_socket,
+      { "Socket",              "asp.socket",   FT_UINT8,  BASE_DEC, 
+               NULL, 0, "asp socket", HFILL }},
+
+    { &hf_asp_seq,
+      { "Sequence",            "asp.seq",      FT_UINT16,  BASE_DEC, 
+               NULL, 0, "asp sequence number", HFILL }},
+
+    { &hf_asp_size,
+      { "size",                "asp.size",     FT_UINT16,  BASE_DEC, 
+               NULL, 0, "asp available size for reply", HFILL }},
+
+    { &hf_asp_zero_value,
+      { "Pad (0)",         "asp.zero_value",
+       FT_BYTES, BASE_HEX, NULL, 0x0,
+       "Pad", HFILL }},
+
+       /* asp ,dsi, afp */
+    { &hf_asp_server_name,
+      { "Server name",         "asp.server_name",
+       FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "Server name", HFILL }},
+
+    { &hf_asp_server_type,
+      { "Server type",         "asp.server_type",
+       FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "Server type", HFILL }},
+
+    { &hf_asp_server_vers,
+      { "AFP version",         "asp.server_vers",
+       FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "AFP version", HFILL }},
+
+    { &hf_asp_server_uams,
+      { "UAM",         "asp.server_uams",
+       FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "UAM", HFILL }},
+
+    { &hf_asp_server_icon,
+      { "Icon bitmap",         "asp.server_icon",
+       FT_BYTES, BASE_HEX, NULL, 0x0,
+       "Server icon bitmap", HFILL }},
+
+    { &hf_asp_server_directory,
+      { "Directory service",         "asp.server_directory",
+       FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "Server directory service", HFILL }},
+
+    { &hf_asp_server_signature,
+      { "Server signature",         "asp.server_signature",
+       FT_BYTES, BASE_HEX, NULL, 0x0,
+       "Server signature", HFILL }},
+
+    { &hf_asp_server_flag,
+      { "Flag",         "asp.server_flag",
+       FT_UINT16, BASE_HEX, NULL, 0x0,
+       "Server capabilities flag", HFILL }},
+    { &hf_asp_server_flag_copyfile,
+      { "Support copyfile",      "asp.server_flag.copyfile",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_COPY,
+       "Server support copyfile", HFILL }},
+    { &hf_asp_server_flag_passwd,
+      { "Support change password",      "asp.server_flag.passwd",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_PASSWD,
+       "Server support change password", HFILL }},
+    { &hf_asp_server_flag_no_save_passwd,
+      { "Don't allow save password",      "asp.server_flag.no_save_passwd",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_NOSAVEPASSWD,
+       "Don't allow save password", HFILL }},
+    { &hf_asp_server_flag_srv_msg,
+      { "Support server message",      "asp.server_flag.srv_msg",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVMSGS,
+       "Support server message", HFILL }},
+    { &hf_asp_server_flag_srv_sig,
+      { "Support server signature",      "asp.server_flag.srv_sig",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVSIGNATURE,
+       "Support server signature", HFILL }},
+    { &hf_asp_server_flag_tcpip,
+      { "Support TCP/IP",      "asp.server_flag.tcpip",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_TCPIP,
+       "Server support TCP/IP", HFILL }},
+    { &hf_asp_server_flag_notify,
+      { "Support server notifications",      "asp.server_flag.notify",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVNOTIFY,
+       "Server support notifications", HFILL }},
+    { &hf_asp_server_flag_reconnect,
+      { "Support server reconnect",      "asp.server_flag.reconnect",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVRECONNECT,
+       "Server support reconnect", HFILL }},
+    { &hf_asp_server_flag_directory,
+      { "Support directory services",      "asp.server_flag.directory",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVDIRECTORY,
+       "Server support directory services", HFILL }},
+    { &hf_asp_server_flag_fast_copy,
+      { "Support fast copy",      "asp.server_flag.fast_copy",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_FASTBOZO,
+       "Server support fast copy", HFILL }},
+
+    { &hf_asp_server_addr_len,
+      { "Length",          "asp.server_addr.len",
+       FT_UINT8, BASE_DEC, NULL, 0x0,
+       "Address length.", HFILL }},
+
+    { &hf_asp_server_addr_type,
+      { "Type",          "asp.server_addr.type",
+       FT_UINT8, BASE_DEC, VALS(afp_server_addr_type_vals), 0x0,
+       "Address type.", HFILL }},
+
+    { &hf_asp_server_addr_value,
+      { "Value",          "asp.server_addr.value",
+       FT_BYTES, BASE_HEX, NULL, 0x0,
+       "Address value", HFILL }},
+
   };
   
   static gint *ett[] = {
@@ -1318,6 +1794,15 @@ proto_register_atalk(void)
        &ett_atp_segments,
        &ett_atp_segment,
        &ett_asp,
+
+       /* asp dsi afp */
+       &ett_asp_status,
+       &ett_asp_status_server_flag,
+       &ett_asp_vers,
+       &ett_asp_uams,
+       &ett_asp_addr,
+       &ett_asp_directory,
+       
        &ett_nbp,
        &ett_nbp_info,
        &ett_nbp_node,
@@ -1388,7 +1873,7 @@ proto_reg_handoff_atalk(void)
   llap_handle = create_dissector_handle(dissect_llap, proto_llap);
   dissector_add("wtap_encap", WTAP_ENCAP_LOCALTALK, llap_handle);
 
-  register_init_routine( atp_defragment_init);
+  register_init_routine( atp_init);
   register_init_routine( &asp_reinit);
 
   afp_handle = find_dissector("afp");
index aebc2afb62a995b82118799198bd09ea984a7f97..e2387cbbd130cde6391cf5839f16b23a67b43a8b 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for dsi packet dissection
  * Copyright 2001, Randy McEoin <rmceoin@pe.com>
  *
- * $Id: packet-dsi.c,v 1.17 2002/05/01 07:07:09 guy Exp $
+ * $Id: packet-dsi.c,v 1.18 2002/05/03 21:25:43 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -84,6 +84,7 @@ static int hf_dsi_server_type = -1;
 static int hf_dsi_server_vers = -1;
 static int hf_dsi_server_uams = -1;
 static int hf_dsi_server_icon = -1;
+static int hf_dsi_server_directory = -1;
 
 static int hf_dsi_server_flag = -1;
 static int hf_dsi_server_flag_copyfile = -1;
@@ -93,6 +94,8 @@ static int hf_dsi_server_flag_srv_msg = -1;
 static int hf_dsi_server_flag_srv_sig  = -1;
 static int hf_dsi_server_flag_tcpip    = -1;
 static int hf_dsi_server_flag_notify   = -1;
+static int hf_dsi_server_flag_reconnect        = -1;
+static int hf_dsi_server_flag_directory        = -1;
 static int hf_dsi_server_flag_fast_copy = -1;
 static int hf_dsi_server_signature     = -1;
 
@@ -104,6 +107,7 @@ static gint ett_dsi_status = -1;
 static gint ett_dsi_uams   = -1;
 static gint ett_dsi_vers   = -1;
 static gint ett_dsi_addr   = -1;
+static gint ett_dsi_directory = -1;
 static gint ett_dsi_status_server_flag = -1;
 
 const value_string afp_server_addr_type_vals[] = {
@@ -168,10 +172,14 @@ dissect_dsi_reply_get_status(tvbuff_t *tvb, proto_tree *tree, gint offset)
        guint16 flag;
        guint16 sign_ofs = 0;
        guint16 adr_ofs = 0;
+       guint16 dir_ofs = 0;
        guint8  nbe;
        guint8  len;
        guint8  i;
                
+       if (!tree)
+               return offset;
+               
        ti = proto_tree_add_text(tree, tvb, offset, -1, "Get Status");
        tree = proto_item_add_subtree(ti, ett_dsi_status);
 
@@ -197,11 +205,12 @@ dissect_dsi_reply_get_status(tvbuff_t *tvb, proto_tree *tree, gint offset)
        proto_tree_add_item(sub_tree, hf_dsi_server_flag_srv_sig       , tvb, ofs, 2, FALSE);
        proto_tree_add_item(sub_tree, hf_dsi_server_flag_tcpip         , tvb, ofs, 2, FALSE);
        proto_tree_add_item(sub_tree, hf_dsi_server_flag_notify        , tvb, ofs, 2, FALSE);
+       proto_tree_add_item(sub_tree, hf_dsi_server_flag_reconnect     , tvb, ofs, 2, FALSE);
+       proto_tree_add_item(sub_tree, hf_dsi_server_flag_directory     , tvb, ofs, 2, FALSE);
        proto_tree_add_item(sub_tree, hf_dsi_server_flag_fast_copy     , tvb, ofs, 2, FALSE);
 
        proto_tree_add_item(tree, hf_dsi_server_name, tvb, offset +AFPSTATUS_PRELEN, 1, FALSE);
 
-       /* FIXME wild guess */
        flag = tvb_get_ntohs(tvb, ofs);
        if ((flag & AFPSRVRINFO_SRVSIGNATURE)) {
                ofs = offset +AFPSTATUS_PRELEN +tvb_get_guint8(tvb, offset +AFPSTATUS_PRELEN);
@@ -218,6 +227,13 @@ dissect_dsi_reply_get_status(tvbuff_t *tvb, proto_tree *tree, gint offset)
                        proto_tree_add_text(tree, tvb, ofs, 2, "Network address offset: %d", adr_ofs);
                        adr_ofs += offset;
                }
+
+               if ((flag & AFPSRVRINFO_SRVDIRECTORY)) {
+                       ofs += 2;
+                       dir_ofs =  tvb_get_ntohs(tvb, ofs);
+                       proto_tree_add_text(tree, tvb, ofs, 2, "Directory services offset: %d", dir_ofs);
+                       dir_ofs += offset;
+               }
        }
                
        ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF);
@@ -274,6 +290,20 @@ dissect_dsi_reply_get_status(tvbuff_t *tvb, proto_tree *tree, gint offset)
                        ofs += len;
                }
        }
+       
+       if (dir_ofs) {
+               ofs = dir_ofs;
+               nbe = tvb_get_guint8(tvb, ofs);
+               ti = proto_tree_add_text(tree, tvb, ofs, 1, "Directory services list: %d", nbe);
+               ofs++;
+               sub_tree = proto_item_add_subtree(ti, ett_dsi_directory);
+               for (i = 0; i < nbe; i++) {
+                       len = tvb_get_guint8(tvb, ofs) +1;
+                       proto_tree_add_item(sub_tree, hf_dsi_server_directory, tvb, ofs, 1, FALSE);
+                       ofs += len;
+               }
+       }
+
        return offset;
 }
 
@@ -449,6 +479,10 @@ dissect_dsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                 * with that exception getting the "Unreassembled Packet"
                 * error.
                 */
+               if (plen > 0x7fffffff) {
+                       show_reported_bounds_error(tvb, pinfo, tree);
+                       return;
+               }                                       
                length = length_remaining;
                if ((guint32)length > plen + 16)
                        length = plen + 16;
@@ -523,7 +557,7 @@ proto_register_dsi(void)
       { "Reserved",         "dsi.reserved",
        FT_UINT32, BASE_HEX, NULL, 0x0,
        "Reserved for future use.  Should be set to zero.", HFILL }},
-
+       /* asp , afp */
     { &hf_dsi_server_name,
       { "Server name",         "dsi.server_name",
        FT_UINT_STRING, BASE_NONE, NULL, 0x0,
@@ -549,6 +583,11 @@ proto_register_dsi(void)
        FT_BYTES, BASE_HEX, NULL, 0x0,
        "Server icon bitmap", HFILL }},
 
+    { &hf_dsi_server_directory,
+      { "Directory service",         "dsi.server_directory",
+       FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "Server directory service", HFILL }},
+
     { &hf_dsi_server_signature,
       { "Server signature",         "dsi.server_signature",
        FT_BYTES, BASE_HEX, NULL, 0x0,
@@ -586,6 +625,14 @@ proto_register_dsi(void)
       { "Support server notifications",      "dsi.server_flag.notify",
                FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVNOTIFY,
        "Server support notifications", HFILL }},
+    { &hf_dsi_server_flag_reconnect,
+      { "Support server reconnect",      "dsi.server_flag.reconnect",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVRECONNECT,
+       "Server support reconnect", HFILL }},
+    { &hf_dsi_server_flag_directory,
+      { "Support directory services",      "dsi.server_flag.directory",
+               FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVDIRECTORY,
+       "Server support directory services", HFILL }},
     { &hf_dsi_server_flag_fast_copy,
       { "Support fast copy",      "dsi.server_flag.fast_copy",
                FT_BOOLEAN, 16, NULL, AFPSRVRINFO_FASTBOZO,
@@ -610,11 +657,13 @@ proto_register_dsi(void)
   };
   static gint *ett[] = {
     &ett_dsi,
+    /* asp afp */
     &ett_dsi_status,
     &ett_dsi_status_server_flag,
     &ett_dsi_vers,
     &ett_dsi_uams,
     &ett_dsi_addr,
+    &ett_dsi_directory,
   };
   module_t *dsi_module;